Coverage Report

Created: 2023-11-19 06:18

/src/njs/src/njs_parser.c
Line
Count
Source (jump to first uncovered line)
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) Alexander Borisov
5
 * Copyright (C) NGINX, Inc.
6
 */
7
8
9
#include <njs_main.h>
10
11
12
static njs_int_t njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type,
13
    njs_bool_t init_this);
14
static void njs_parser_scope_end(njs_parser_t *parser);
15
16
static njs_int_t njs_parser_check_error_state(njs_parser_t *parser,
17
    njs_lexer_token_t *token, njs_queue_link_t *current);
18
19
static njs_int_t njs_parser_primary_expression_test(njs_parser_t *parser,
20
    njs_lexer_token_t *token, njs_queue_link_t *current);
21
static njs_int_t njs_parser_regexp_literal(njs_parser_t *parser,
22
    njs_lexer_token_t *token, njs_queue_link_t *current);
23
static njs_int_t njs_parser_template_literal(njs_parser_t *parser,
24
    njs_lexer_token_t *token, njs_queue_link_t *current);
25
static njs_int_t njs_parser_template_literal_string(njs_parser_t *parser,
26
    njs_lexer_token_t *token, njs_queue_link_t *current);
27
static njs_int_t njs_parser_template_literal_expression(
28
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
29
static njs_int_t njs_parser_cover_parenthesized_expression(
30
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
31
static njs_int_t njs_parser_binding_identifier_pattern(njs_parser_t *parser,
32
    njs_lexer_token_t *token, njs_queue_link_t *current);
33
static njs_int_t njs_parser_cover_parenthesized_expression_after(
34
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
35
static njs_int_t njs_parser_cover_parenthesized_expression_end(
36
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
37
38
static njs_int_t njs_parser_array_literal(njs_parser_t *parser,
39
    njs_lexer_token_t *token, njs_queue_link_t *current);
40
static njs_int_t njs_parser_array_element_list(njs_parser_t *parser,
41
    njs_lexer_token_t *token, njs_queue_link_t *current);
42
static njs_int_t njs_parser_array_after(njs_parser_t *parser,
43
    njs_lexer_token_t *token, njs_queue_link_t *current);
44
static njs_int_t njs_parser_array_spread_element(njs_parser_t *parser,
45
    njs_lexer_token_t *token, njs_queue_link_t *current);
46
47
static njs_int_t njs_parser_object_literal(njs_parser_t *parser,
48
    njs_lexer_token_t *token, njs_queue_link_t *current);
49
static njs_int_t njs_parser_object_literal_after(njs_parser_t *parser,
50
    njs_lexer_token_t *token, njs_queue_link_t *current);
51
static njs_int_t njs_parser_property_definition_list(njs_parser_t *parser,
52
    njs_lexer_token_t *token, njs_queue_link_t *current);
53
static njs_int_t njs_parser_property_definition_list_after(
54
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
55
static njs_int_t njs_parser_property_definition(njs_parser_t *parser,
56
    njs_lexer_token_t *token, njs_queue_link_t *current);
57
static njs_int_t njs_parser_property_definition_after(njs_parser_t *parser,
58
    njs_lexer_token_t *token, njs_queue_link_t *current);
59
static njs_int_t njs_parser_computed_property_name_after(njs_parser_t *parser,
60
    njs_lexer_token_t *token, njs_queue_link_t *current);
61
static njs_int_t njs_parser_computed_property_async_after(njs_parser_t *parser,
62
    njs_lexer_token_t *token, njs_queue_link_t *current);
63
static njs_int_t njs_parser_computed_property_name_handler(njs_parser_t *parser,
64
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async);
65
66
static njs_int_t njs_parser_initializer(njs_parser_t *parser,
67
    njs_lexer_token_t *token, njs_queue_link_t *current);
68
static njs_int_t njs_parser_initializer_after(njs_parser_t *parser,
69
    njs_lexer_token_t *token, njs_queue_link_t *current);
70
static njs_int_t njs_parser_initializer_assign(njs_parser_t *parser,
71
    njs_token_type_t type);
72
73
static njs_int_t njs_parser_member_expression(njs_parser_t *parser,
74
    njs_lexer_token_t *token, njs_queue_link_t *current);
75
static njs_int_t njs_parser_member_expression_next(njs_parser_t *parser,
76
    njs_lexer_token_t *token, njs_queue_link_t *current);
77
static njs_int_t njs_parser_member_expression_bracket(njs_parser_t *parser,
78
    njs_lexer_token_t *token, njs_queue_link_t *current);
79
static njs_int_t njs_parser_member_expression_new_next(njs_parser_t *parser,
80
    njs_lexer_token_t *token, njs_queue_link_t *current);
81
static njs_int_t njs_parser_super_property(njs_parser_t *parser,
82
    njs_lexer_token_t *token, njs_queue_link_t *current);
83
static njs_int_t njs_parser_member_expression_import(njs_parser_t *parser,
84
    njs_lexer_token_t *token, njs_queue_link_t *current);
85
static njs_int_t njs_parser_member_expression_new(njs_parser_t *parser,
86
    njs_lexer_token_t *token, njs_queue_link_t *current);
87
static njs_int_t njs_parser_member_expression_new_after(njs_parser_t *parser,
88
    njs_lexer_token_t *token, njs_queue_link_t *current);
89
static njs_int_t njs_parser_member_expression_new_args(njs_parser_t *parser,
90
    njs_lexer_token_t *token, njs_queue_link_t *current);
91
92
static njs_parser_node_t *njs_parser_create_call(njs_parser_t *parser,
93
    njs_parser_node_t *node, uint8_t ctor);
94
static njs_int_t njs_parser_call_expression(njs_parser_t *parser,
95
    njs_lexer_token_t *token, njs_queue_link_t *current);
96
static njs_int_t njs_parser_call_expression_args(njs_parser_t *parser,
97
    njs_lexer_token_t *token, njs_queue_link_t *current);
98
static njs_int_t njs_parser_call_expression_after(njs_parser_t *parser,
99
    njs_lexer_token_t *token, njs_queue_link_t *current);
100
static njs_int_t njs_parser_arguments(njs_parser_t *parser,
101
    njs_lexer_token_t *token, njs_queue_link_t *current);
102
static njs_int_t njs_parser_parenthesis_or_comma(njs_parser_t *parser,
103
    njs_lexer_token_t *token, njs_queue_link_t *current);
104
static njs_int_t njs_parser_argument_list(njs_parser_t *parser,
105
    njs_lexer_token_t *token, njs_queue_link_t *current);
106
static njs_int_t njs_parser_argument_list_after(njs_parser_t *parser,
107
    njs_lexer_token_t *token, njs_queue_link_t *current);
108
static njs_int_t njs_parser_optional_expression_after(njs_parser_t *parser,
109
    njs_lexer_token_t *token, njs_queue_link_t *current);
110
static njs_int_t njs_parser_optional_chain(njs_parser_t *parser,
111
    njs_lexer_token_t *token, njs_queue_link_t *current);
112
static njs_int_t njs_parser_optional_chain_after(njs_parser_t *parser,
113
    njs_lexer_token_t *token, njs_queue_link_t *current);
114
static njs_int_t njs_parser_new_expression(njs_parser_t *parser,
115
    njs_lexer_token_t *token, njs_queue_link_t *current);
116
static njs_int_t njs_parser_new_expression_after(njs_parser_t *parser,
117
    njs_lexer_token_t *token, njs_queue_link_t *current);
118
static njs_int_t njs_parser_left_hand_side_expression(njs_parser_t *parser,
119
    njs_lexer_token_t *token, njs_queue_link_t *current);
120
static njs_int_t njs_parser_left_hand_side_expression_after(
121
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
122
static njs_int_t njs_parser_left_hand_side_expression_node(
123
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
124
static njs_int_t njs_parser_left_hand_side_expression_optional(
125
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
126
static njs_int_t njs_parser_update_expression(njs_parser_t *parser,
127
    njs_lexer_token_t *token, njs_queue_link_t *current);
128
static njs_int_t njs_parser_update_expression_post(njs_parser_t *parser,
129
    njs_lexer_token_t *token, njs_queue_link_t *current);
130
static njs_int_t njs_parser_update_expression_unary(njs_parser_t *parser,
131
    njs_lexer_token_t *token, njs_queue_link_t *current);
132
133
static njs_int_t njs_parser_unary_expression(njs_parser_t *parser,
134
    njs_lexer_token_t *token, njs_queue_link_t *current);
135
static njs_int_t njs_parser_unary_expression_after(njs_parser_t *parser,
136
    njs_lexer_token_t *token, njs_queue_link_t *current);
137
static njs_int_t njs_parser_unary_expression_next(njs_parser_t *parser,
138
    njs_lexer_token_t *token, njs_queue_link_t *current);
139
static njs_int_t njs_parser_await(njs_parser_t *parser,
140
    njs_lexer_token_t *token, njs_queue_link_t *current);
141
static njs_int_t njs_parser_await_after(njs_parser_t *parser,
142
    njs_lexer_token_t *token, njs_queue_link_t *current);
143
144
static njs_int_t njs_parser_exponentiation_expression(njs_parser_t *parser,
145
    njs_lexer_token_t *token, njs_queue_link_t *current);
146
static njs_int_t njs_parser_exponentiation_expression_match(
147
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
148
149
static njs_int_t njs_parser_multiplicative_expression(njs_parser_t *parser,
150
    njs_lexer_token_t *token, njs_queue_link_t *current);
151
static njs_int_t njs_parser_multiplicative_expression_match(
152
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
153
154
static njs_int_t njs_parser_additive_expression(njs_parser_t *parser,
155
    njs_lexer_token_t *token, njs_queue_link_t *current);
156
static njs_int_t njs_parser_additive_expression_match(njs_parser_t *parser,
157
    njs_lexer_token_t *token, njs_queue_link_t *current);
158
159
static njs_int_t njs_parser_shift_expression(njs_parser_t *parser,
160
    njs_lexer_token_t *token, njs_queue_link_t *current);
161
static njs_int_t njs_parser_shift_expression_match(njs_parser_t *parser,
162
    njs_lexer_token_t *token, njs_queue_link_t *current);
163
164
static njs_int_t njs_parser_relational_expression(njs_parser_t *parser,
165
    njs_lexer_token_t *token, njs_queue_link_t *current);
166
static njs_int_t njs_parser_relational_expression_match(njs_parser_t *parser,
167
    njs_lexer_token_t *token, njs_queue_link_t *current);
168
169
static njs_int_t njs_parser_equality_expression(njs_parser_t *parser,
170
    njs_lexer_token_t *token, njs_queue_link_t *current);
171
static njs_int_t njs_parser_equality_expression_match(njs_parser_t *parser,
172
    njs_lexer_token_t *token, njs_queue_link_t *current);
173
174
static njs_int_t njs_parser_bitwise_AND_expression(njs_parser_t *parser,
175
    njs_lexer_token_t *token, njs_queue_link_t *current);
176
static njs_int_t njs_parser_bitwise_AND_expression_and(njs_parser_t *parser,
177
    njs_lexer_token_t *token, njs_queue_link_t *current);
178
static njs_int_t njs_parser_bitwise_XOR_expression(njs_parser_t *parser,
179
    njs_lexer_token_t *token, njs_queue_link_t *current);
180
static njs_int_t njs_parser_bitwise_XOR_expression_xor(njs_parser_t *parser,
181
    njs_lexer_token_t *token, njs_queue_link_t *current);
182
static njs_int_t njs_parser_bitwise_OR_expression(njs_parser_t *parser,
183
    njs_lexer_token_t *token, njs_queue_link_t *current);
184
static njs_int_t njs_parser_bitwise_OR_expression_or(njs_parser_t *parser,
185
    njs_lexer_token_t *token, njs_queue_link_t *current);
186
187
static njs_int_t njs_parser_logical_AND_expression(njs_parser_t *parser,
188
    njs_lexer_token_t *token, njs_queue_link_t *current);
189
static njs_int_t njs_parser_logical_AND_expression_and(njs_parser_t *parser,
190
    njs_lexer_token_t *token, njs_queue_link_t *current);
191
static njs_int_t njs_parser_logical_OR_expression(njs_parser_t *parser,
192
    njs_lexer_token_t *token, njs_queue_link_t *current);
193
static njs_int_t njs_parser_logical_OR_expression_or(njs_parser_t *parser,
194
    njs_lexer_token_t *token, njs_queue_link_t *current);
195
static njs_int_t njs_parser_coalesce_expression(njs_parser_t *parser,
196
    njs_lexer_token_t *token, njs_queue_link_t *current);
197
static njs_int_t njs_parser_short_circuit_expression(njs_parser_t *parser,
198
    njs_lexer_token_t *token, njs_queue_link_t *current);
199
200
static njs_int_t njs_parser_conditional_expression(njs_parser_t *parser,
201
    njs_lexer_token_t *token, njs_queue_link_t *current);
202
static njs_int_t njs_parser_conditional_question_mark(njs_parser_t *parser,
203
    njs_lexer_token_t *token, njs_queue_link_t *current);
204
static njs_int_t njs_parser_conditional_colon(njs_parser_t *parser,
205
    njs_lexer_token_t *token, njs_queue_link_t *current);
206
static njs_int_t njs_parser_conditional_colon_after(njs_parser_t *parser,
207
    njs_lexer_token_t *token, njs_queue_link_t *current);
208
209
static njs_int_t njs_parser_assignment_expression(njs_parser_t *parser,
210
    njs_lexer_token_t *token, njs_queue_link_t *current);
211
static njs_int_t njs_parser_match_arrow_expression(njs_parser_t *parser,
212
    njs_lexer_token_t *token);
213
static njs_int_t njs_parser_assignment_expression_after(njs_parser_t *parser,
214
    njs_lexer_token_t *token, njs_queue_link_t *current);
215
static njs_int_t njs_parser_assignment_operator(njs_parser_t *parser,
216
    njs_lexer_token_t *token, njs_queue_link_t *current);
217
static njs_int_t njs_parser_assignment_operator_after(njs_parser_t *parser,
218
    njs_lexer_token_t *token, njs_queue_link_t *current);
219
220
static njs_int_t njs_parser_expression(njs_parser_t *parser,
221
    njs_lexer_token_t *token, njs_queue_link_t *current);
222
static njs_int_t njs_parser_expression_comma(njs_parser_t *parser,
223
    njs_lexer_token_t *token, njs_queue_link_t *current);
224
225
static njs_int_t njs_parser_statement(njs_parser_t *parser,
226
    njs_lexer_token_t *token, njs_queue_link_t *current);
227
static njs_int_t njs_parser_statement_wo_node(njs_parser_t *parser,
228
    njs_lexer_token_t *token, njs_queue_link_t *current);
229
static njs_int_t njs_parser_statement_after(njs_parser_t *parser,
230
    njs_lexer_token_t *token, njs_queue_link_t *current);
231
static njs_int_t njs_parser_declaration(njs_parser_t *parser,
232
    njs_lexer_token_t *token, njs_queue_link_t *current);
233
static njs_int_t njs_parser_hoistable_declaration(njs_parser_t *parser,
234
    njs_lexer_token_t *token, njs_queue_link_t *current);
235
236
static njs_int_t njs_parser_block_statement(njs_parser_t *parser,
237
    njs_lexer_token_t *token, njs_queue_link_t *current);
238
static njs_int_t njs_parser_block_statement_open_brace(njs_parser_t *parser,
239
    njs_lexer_token_t *token, njs_queue_link_t *current);
240
static njs_int_t njs_parser_block_statement_close_brace(njs_parser_t *parser,
241
    njs_lexer_token_t *token, njs_queue_link_t *current);
242
static njs_int_t njs_parser_statement_list(njs_parser_t *parser,
243
    njs_lexer_token_t *token, njs_queue_link_t *current);
244
static njs_int_t njs_parser_statement_list_next(njs_parser_t *parser,
245
    njs_lexer_token_t *token, njs_queue_link_t *current);
246
static njs_int_t njs_parser_statement_list_item(njs_parser_t *parser,
247
    njs_lexer_token_t *token, njs_queue_link_t *current);
248
249
static njs_int_t njs_parser_lexical_declaration(njs_parser_t *parser,
250
    njs_lexer_token_t *token, njs_queue_link_t *current);
251
static njs_int_t njs_parser_variable_statement(njs_parser_t *parser,
252
    njs_lexer_token_t *token, njs_queue_link_t *current);
253
static njs_int_t njs_parser_variable_declaration_list(njs_parser_t *parser,
254
    njs_lexer_token_t *token, njs_queue_link_t *current);
255
static njs_int_t njs_parser_variable_declaration_list_next(
256
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
257
static njs_int_t njs_parser_variable_declaration(njs_parser_t *parser,
258
    njs_lexer_token_t *token, njs_queue_link_t *current);
259
260
static njs_int_t njs_parser_binding_pattern(njs_parser_t *parser,
261
    njs_lexer_token_t *token, njs_queue_link_t *current);
262
static njs_int_t njs_parser_object_binding_pattern(njs_parser_t *parser,
263
    njs_lexer_token_t *token, njs_queue_link_t *current);
264
static njs_int_t njs_parser_array_binding_pattern(njs_parser_t *parser,
265
    njs_lexer_token_t *token, njs_queue_link_t *current);
266
267
static njs_int_t njs_parser_expression_statement(njs_parser_t *parser,
268
    njs_lexer_token_t *token, njs_queue_link_t *current);
269
static njs_int_t njs_parser_expression_statement_after(njs_parser_t *parser,
270
    njs_lexer_token_t *token, njs_queue_link_t *current);
271
272
static njs_int_t njs_parser_if_statement(njs_parser_t *parser,
273
    njs_lexer_token_t *token, njs_queue_link_t *current);
274
static njs_int_t njs_parser_if_close_parenthesis(njs_parser_t *parser,
275
    njs_lexer_token_t *token, njs_queue_link_t *current);
276
static njs_int_t njs_parser_else_statement(njs_parser_t *parser,
277
    njs_lexer_token_t *token, njs_queue_link_t *current);
278
static njs_int_t njs_parser_else_statement_after(njs_parser_t *parser,
279
    njs_lexer_token_t *token, njs_queue_link_t *current);
280
281
static njs_int_t njs_parser_iteration_statement_do(njs_parser_t *parser,
282
    njs_lexer_token_t *token, njs_queue_link_t *current);
283
static njs_int_t njs_parser_iteration_statement_do_while(njs_parser_t *parser,
284
    njs_lexer_token_t *token, njs_queue_link_t *current);
285
static njs_int_t njs_parser_do_while_semicolon(njs_parser_t *parser,
286
    njs_lexer_token_t *token, njs_queue_link_t *current);
287
288
static njs_int_t njs_parser_iteration_statement_while(njs_parser_t *parser,
289
    njs_lexer_token_t *token, njs_queue_link_t *current);
290
static njs_int_t njs_parser_while_statement(njs_parser_t *parser,
291
    njs_lexer_token_t *token, njs_queue_link_t *current);
292
static njs_int_t njs_parser_while_after(njs_parser_t *parser,
293
    njs_lexer_token_t *token, njs_queue_link_t *current);
294
295
static njs_int_t njs_parser_iteration_statement_for(njs_parser_t *parser,
296
    njs_lexer_token_t *token, njs_queue_link_t *current);
297
static njs_int_t njs_parser_for_expression_map_continue(
298
    njs_parser_t *parser, njs_lexer_token_t *token,
299
    njs_queue_link_t *current);
300
static njs_int_t njs_parser_for_expression_map_reparse(
301
    njs_parser_t *parser, njs_lexer_token_t *token,
302
    njs_queue_link_t *current);
303
static njs_int_t njs_parser_expression_continue_op(njs_parser_t *parser,
304
    njs_lexer_token_t *token, njs_queue_link_t *current);
305
static njs_int_t njs_parser_expression_continue_assign_comma(
306
    njs_parser_t *parser, njs_lexer_token_t *token,
307
    njs_queue_link_t *current);
308
static njs_int_t njs_parser_for_in_statement_statement(njs_parser_t *parser,
309
    njs_lexer_token_t *token, njs_queue_link_t *current);
310
static njs_int_t njs_parser_iteration_statement_for_map(njs_parser_t *parser,
311
    njs_lexer_token_t *token, njs_queue_link_t *current);
312
static njs_int_t njs_parser_for_var_binding_or_var_list(njs_parser_t *parser,
313
    njs_lexer_token_t *token, njs_queue_link_t *current,
314
    njs_token_type_t token_type);
315
static njs_int_t njs_parser_for_var_in_statement(njs_parser_t *parser,
316
    njs_lexer_token_t *token, njs_queue_link_t *current);
317
static njs_int_t njs_parser_for_var_in_statement_after(njs_parser_t *parser,
318
    njs_lexer_token_t *token, njs_queue_link_t *current);
319
static njs_int_t njs_parser_for_var_in_of_expression(njs_parser_t *parser,
320
    njs_lexer_token_t *token, njs_queue_link_t *current);
321
static njs_int_t njs_parser_for_in_statement(njs_parser_t *parser,
322
    njs_lexer_token_t *token, njs_queue_link_t *current);
323
static njs_int_t njs_parser_for_in_statement_after(njs_parser_t *parser,
324
    njs_lexer_token_t *token, njs_queue_link_t *current);
325
static njs_int_t njs_parser_for_expression(njs_parser_t *parser,
326
    njs_lexer_token_t *token, njs_queue_link_t *current);
327
static njs_int_t njs_parser_for_expression_end(njs_parser_t *parser,
328
    njs_lexer_token_t *token, njs_queue_link_t *current);
329
static njs_int_t njs_parser_for_end(njs_parser_t *parser,
330
    njs_lexer_token_t *token, njs_queue_link_t *current);
331
332
static njs_int_t njs_parser_switch_statement(njs_parser_t *parser,
333
    njs_lexer_token_t *token, njs_queue_link_t *current);
334
static njs_int_t njs_parser_switch_statement_after(njs_parser_t *parser,
335
    njs_lexer_token_t *token, njs_queue_link_t *current);
336
static njs_int_t njs_parser_switch_block(njs_parser_t *parser,
337
    njs_lexer_token_t *token, njs_queue_link_t *current);
338
static njs_int_t njs_parser_switch_block_after(njs_parser_t *parser,
339
    njs_lexer_token_t *token, njs_queue_link_t *current);
340
static njs_int_t njs_parser_switch_case(njs_parser_t *parser,
341
    njs_lexer_token_t *token, njs_queue_link_t *current);
342
static njs_int_t njs_parser_switch_case_wo_def(njs_parser_t *parser,
343
    njs_lexer_token_t *token, njs_queue_link_t *current);
344
static njs_int_t njs_parser_switch_case_def(njs_parser_t *parser,
345
    njs_lexer_token_t *token, njs_queue_link_t *current,
346
    njs_bool_t with_default);
347
static njs_int_t njs_parser_switch_case_after(njs_parser_t *parser,
348
    njs_lexer_token_t *token, njs_queue_link_t *current);
349
static njs_int_t njs_parser_switch_case_block(njs_parser_t *parser,
350
    njs_lexer_token_t *token, njs_queue_link_t *current);
351
static njs_int_t njs_parser_switch_case_after_wo_def(njs_parser_t *parser,
352
    njs_lexer_token_t *token, njs_queue_link_t *current);
353
static njs_int_t njs_parser_switch_case_block_wo_def(njs_parser_t *parser,
354
    njs_lexer_token_t *token, njs_queue_link_t *current);
355
356
static njs_int_t njs_parser_continue_statement(njs_parser_t *parser,
357
    njs_lexer_token_t *token, njs_queue_link_t *current);
358
359
static njs_int_t njs_parser_break_statement(njs_parser_t *parser,
360
    njs_lexer_token_t *token, njs_queue_link_t *current);
361
362
static njs_int_t njs_parser_break_continue(njs_parser_t *parser,
363
    njs_lexer_token_t *token, njs_token_type_t type);
364
365
static njs_int_t njs_parser_return_statement(njs_parser_t *parser,
366
    njs_lexer_token_t *token, njs_queue_link_t *current);
367
static njs_int_t njs_parser_return_statement_after(njs_parser_t *parser,
368
    njs_lexer_token_t *token, njs_queue_link_t *current);
369
370
static njs_int_t njs_parser_with_statement(njs_parser_t *parser,
371
    njs_lexer_token_t *token, njs_queue_link_t *current);
372
373
static njs_int_t njs_parser_labelled_statement(njs_parser_t *parser,
374
    njs_lexer_token_t *token, njs_queue_link_t *current);
375
static njs_int_t njs_parser_labelled_statement_after(njs_parser_t *parser,
376
    njs_lexer_token_t *token, njs_queue_link_t *current);
377
378
static njs_int_t njs_parser_throw_statement(njs_parser_t *parser,
379
    njs_lexer_token_t *token, njs_queue_link_t *current);
380
static njs_int_t njs_parser_throw_statement_after(njs_parser_t *parser,
381
    njs_lexer_token_t *token, njs_queue_link_t *current);
382
383
static njs_int_t njs_parser_try_statement(njs_parser_t *parser,
384
    njs_lexer_token_t *token, njs_queue_link_t *current);
385
static njs_int_t njs_parser_catch_or_finally(njs_parser_t *parser,
386
    njs_lexer_token_t *token, njs_queue_link_t *current);
387
static njs_int_t njs_parser_catch_after(njs_parser_t *parser,
388
    njs_lexer_token_t *token, njs_queue_link_t *current);
389
static njs_int_t njs_parser_catch_parenthesis(njs_parser_t *parser,
390
    njs_lexer_token_t *token, njs_queue_link_t *current);
391
static njs_int_t njs_parser_catch_statement_open_brace(njs_parser_t *parser,
392
    njs_lexer_token_t *token, njs_queue_link_t *current);
393
static njs_int_t njs_parser_catch_finally(njs_parser_t *parser,
394
    njs_lexer_token_t *token, njs_queue_link_t *current);
395
396
static njs_int_t njs_parser_debugger_statement(njs_parser_t *parser,
397
    njs_lexer_token_t *token, njs_queue_link_t *current);
398
399
static njs_int_t njs_parser_function_declaration(njs_parser_t *parser,
400
    njs_lexer_token_t *token, njs_queue_link_t *current);
401
static njs_int_t njs_parser_function_declaration_after(njs_parser_t *parser,
402
    njs_lexer_token_t *token, njs_queue_link_t *current);
403
static njs_int_t njs_parser_function_parse(njs_parser_t *parser,
404
    njs_lexer_token_t *token, njs_queue_link_t *current);
405
static njs_int_t njs_parser_function_expression(njs_parser_t *parser,
406
    njs_lexer_token_t *token, njs_queue_link_t *current);
407
static njs_int_t njs_parser_function_expression_after(njs_parser_t *parser,
408
    njs_lexer_token_t *token, njs_queue_link_t *current);
409
static njs_int_t njs_parser_unique_formal_parameters(njs_parser_t *parser,
410
    njs_lexer_token_t *token, njs_queue_link_t *current);
411
static njs_int_t njs_parser_formal_parameters(njs_parser_t *parser,
412
    njs_lexer_token_t *token, njs_queue_link_t *current);
413
static njs_int_t njs_parser_formal_parameters_after(njs_parser_t *parser,
414
    njs_lexer_token_t *token, njs_queue_link_t *current);
415
416
static njs_int_t njs_parser_arrow_function(njs_parser_t *parser,
417
    njs_lexer_token_t *token, njs_queue_link_t *current);
418
static njs_int_t njs_parser_arrow_function_args_after(njs_parser_t *parser,
419
    njs_lexer_token_t *token, njs_queue_link_t *current);
420
static njs_int_t njs_parser_arrow_function_arrow(njs_parser_t *parser,
421
    njs_lexer_token_t *token, njs_queue_link_t *current);
422
static njs_int_t njs_parser_arrow_function_body_after(njs_parser_t *parser,
423
    njs_lexer_token_t *token, njs_queue_link_t *current);
424
425
static njs_int_t njs_parser_method_definition(njs_parser_t *parser,
426
    njs_lexer_token_t *token, njs_queue_link_t *current);
427
static njs_int_t njs_parser_get_set(njs_parser_t *parser,
428
    njs_lexer_token_t *token, njs_queue_link_t *current);
429
static njs_int_t njs_parser_get_set_after(njs_parser_t *parser,
430
    njs_lexer_token_t *token, njs_queue_link_t *current);
431
static njs_int_t njs_parser_get_after(njs_parser_t *parser,
432
    njs_lexer_token_t *token, njs_queue_link_t *current);
433
static njs_int_t njs_parser_set_after(njs_parser_t *parser,
434
    njs_lexer_token_t *token, njs_queue_link_t *current);
435
static njs_int_t njs_parser_function_lambda(njs_parser_t *parser,
436
    njs_lexer_token_t *token, njs_queue_link_t *current);
437
static njs_int_t njs_parser_function_lambda_args_after(njs_parser_t *parser,
438
    njs_lexer_token_t *token, njs_queue_link_t *current);
439
static njs_int_t njs_parser_function_lambda_body_after(njs_parser_t *parser,
440
    njs_lexer_token_t *token, njs_queue_link_t *current);
441
442
static njs_int_t njs_parser_export(njs_parser_t *parser,
443
    njs_lexer_token_t *token, njs_queue_link_t *current);
444
static njs_int_t njs_parser_export_after(njs_parser_t *parser,
445
    njs_lexer_token_t *token, njs_queue_link_t *current);
446
447
static njs_int_t njs_parser_import(njs_parser_t *parser,
448
    njs_lexer_token_t *token, njs_queue_link_t *current);
449
static njs_int_t njs_parser_export_sink(njs_parser_t *parser);
450
451
static njs_parser_node_t *njs_parser_return_set(njs_parser_t *parser,
452
    njs_parser_node_t *expr);
453
static njs_parser_node_t *njs_parser_variable_node(njs_parser_t *parser,
454
    uintptr_t unique_id, njs_variable_type_t type, njs_variable_t  **retvar);
455
456
static njs_parser_node_t *njs_parser_reference(njs_parser_t *parser,
457
    njs_lexer_token_t *token);
458
459
static njs_parser_node_t *njs_parser_argument(njs_parser_t *parser,
460
    njs_parser_node_t *expr, njs_index_t index);
461
462
static njs_int_t njs_parser_object_property(njs_parser_t *parser,
463
    njs_parser_node_t *parent, njs_parser_node_t *property,
464
    njs_parser_node_t *value, njs_bool_t proto_init);
465
static njs_int_t njs_parser_property_accessor(njs_parser_t *parser,
466
    njs_parser_node_t *parent, njs_parser_node_t *property,
467
    njs_parser_node_t *value, njs_token_type_t accessor);
468
static njs_int_t njs_parser_array_item(njs_parser_t *parser,
469
    njs_parser_node_t *array, njs_parser_node_t *value);
470
static njs_int_t njs_parser_template_string(njs_parser_t *parser,
471
    njs_lexer_token_t *token);
472
static njs_token_type_t njs_parser_escape_string_create(njs_parser_t *parser,
473
    njs_lexer_token_t *token, njs_value_t *value);
474
static njs_int_t njs_parser_escape_string_calc_length(njs_parser_t *parser,
475
    njs_lexer_token_t *token, size_t *out_size, size_t *out_length);
476
477
static void njs_parser_serialize_tree(njs_chb_t *chain,
478
    njs_parser_node_t *node, njs_int_t *ret, size_t indent);
479
static njs_int_t njs_parser_serialize_node(njs_chb_t *chain,
480
    njs_parser_node_t *node);
481
482
483
#define njs_parser_chain_top(parser)                                          \
484
68.9k
    ((parser)->scope->top)
485
486
487
#define njs_parser_chain_top_set(parser, node)                                \
488
591k
    (parser)->scope->top = node
489
490
491
njs_inline njs_int_t
492
njs_parser_not_supported(njs_parser_t *parser, njs_lexer_token_t *token)
493
5.13k
{
494
5.13k
    if (token->type != NJS_TOKEN_END) {
495
5.13k
        njs_parser_syntax_error(parser, "Token \"%V\" not supported "
496
5.13k
                                "in this version", &token->text);
497
5.13k
    } else {
498
0
        njs_parser_syntax_error(parser, "Not supported in this version");
499
0
    }
500
501
5.13k
    return NJS_DONE;
502
5.13k
}
503
504
505
njs_inline njs_int_t
506
njs_parser_reject(njs_parser_t *parser)
507
8.44k
{
508
8.44k
    njs_queue_link_t          *link;
509
8.44k
    njs_parser_stack_entry_t  *entry;
510
511
187k
    while (!njs_queue_is_empty(&parser->stack)) {
512
187k
        entry = njs_queue_link_data(njs_queue_first(&parser->stack),
513
187k
                                    njs_parser_stack_entry_t, link);
514
515
187k
        link = njs_queue_first(&parser->stack);
516
187k
        njs_queue_remove(link);
517
518
187k
        if (!entry->optional) {
519
8.44k
            njs_parser_next(parser, entry->state);
520
8.44k
            parser->target = entry->node;
521
522
8.44k
            return NJS_DECLINED;
523
8.44k
        }
524
187k
    }
525
526
0
    return njs_parser_failed(parser);
527
8.44k
}
528
529
530
njs_int_t
531
njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope,
532
    njs_str_t *file, u_char *start, u_char *end, njs_uint_t runtime)
533
51.0k
{
534
51.0k
    njs_lexer_t  *lexer;
535
536
51.0k
    njs_memzero(parser, sizeof(njs_parser_t));
537
538
51.0k
    parser->scope = scope;
539
540
51.0k
    lexer = &parser->lexer0;
541
51.0k
    parser->lexer = lexer;
542
543
51.0k
    parser->use_lhs = 0;
544
545
51.0k
    return njs_lexer_init(vm, lexer, file, start, end, runtime, 0);
546
51.0k
}
547
548
549
njs_int_t
550
njs_parser(njs_vm_t *vm, njs_parser_t *parser)
551
51.0k
{
552
51.0k
    njs_int_t                        ret;
553
51.0k
    njs_str_t                        str;
554
51.0k
    njs_lexer_token_t                *token;
555
51.0k
    const njs_lexer_keyword_entry_t  *keyword;
556
557
51.0k
    parser->vm = vm;
558
559
51.0k
    njs_set_invalid(&vm->exception);
560
561
51.0k
    if (parser->scope == NULL) {
562
51.0k
        ret = njs_parser_scope_begin(parser,
563
51.0k
                                     parser->module ? NJS_SCOPE_FUNCTION
564
51.0k
                                                    : NJS_SCOPE_GLOBAL, 1);
565
51.0k
        if (njs_slow_path(ret != NJS_OK)) {
566
0
            return NJS_ERROR;
567
0
        }
568
569
51.0k
    } else {
570
0
        parser->scope->top = NULL;
571
0
        parser->node = NULL;
572
0
        parser->ret = NJS_OK;
573
0
    }
574
575
    /* Add this as first variable. */
576
51.0k
    njs_string_get(&njs_string_undefined, &str);
577
578
51.0k
    keyword = njs_lexer_keyword(str.start, str.length);
579
51.0k
    if (njs_slow_path(keyword == NULL)) {
580
0
        return NJS_ERROR;
581
0
    }
582
583
51.0k
    parser->undefined_id = (uintptr_t) keyword->value;
584
585
51.0k
    njs_queue_init(&parser->stack);
586
587
51.0k
    parser->target = NULL;
588
51.0k
    njs_parser_next(parser, njs_parser_statement_list);
589
590
51.0k
    ret = njs_parser_after(parser, njs_queue_first(&parser->stack),
591
51.0k
                           NULL, 0, njs_parser_check_error_state);
592
51.0k
    if (ret != NJS_OK) {
593
0
        return ret;
594
0
    }
595
596
101M
    do {
597
101M
        token = njs_lexer_token(parser->lexer, 0);
598
101M
        if (njs_slow_path(token == NULL)) {
599
0
            return NJS_ERROR;
600
0
        }
601
602
101M
        parser->ret = parser->state(parser, token,
603
101M
                                    njs_queue_first(&parser->stack));
604
605
101M
    } while (parser->ret != NJS_DONE && parser->ret != NJS_ERROR);
606
607
51.0k
    if (parser->ret != NJS_DONE) {
608
10.6k
        return NJS_ERROR;
609
10.6k
    }
610
611
40.4k
    if (njs_is_error(&vm->exception)) {
612
36.1k
        return NJS_ERROR;
613
36.1k
    }
614
615
4.28k
    if (parser->node == NULL) {
616
        /* Empty string, just semicolons or variables declarations. */
617
618
0
        parser->node = njs_parser_node_new(parser, 0);
619
0
        if (njs_slow_path(parser->node == NULL)) {
620
0
            return NJS_ERROR;
621
0
        }
622
0
    }
623
624
4.28k
    if (parser->module) {
625
0
        ret = njs_parser_export_sink(parser);
626
0
        if (ret != NJS_OK) {
627
0
            return NJS_ERROR;
628
0
        }
629
630
4.28k
    } else {
631
4.28k
        parser->node->token_type = NJS_TOKEN_END;
632
4.28k
        parser->node->token_line = parser->lexer->line;
633
634
4.28k
        njs_parser_chain_top_set(parser, parser->node);
635
4.28k
    }
636
637
4.28k
    return NJS_OK;
638
4.28k
}
639
640
641
static njs_int_t
642
njs_parser_check_error_state(njs_parser_t *parser, njs_lexer_token_t *token,
643
    njs_queue_link_t *current)
644
5.11k
{
645
5.11k
    return njs_parser_failed(parser);
646
5.11k
}
647
648
649
njs_int_t
650
njs_parser_failed_state(njs_parser_t *parser, njs_lexer_token_t *token,
651
    njs_queue_link_t *current)
652
26.7k
{
653
26.7k
    if (token->type != NJS_TOKEN_END) {
654
26.7k
        njs_parser_syntax_error(parser, "Unexpected token \"%V\"",
655
26.7k
                                &token->text);
656
26.7k
    } else {
657
32
        njs_parser_syntax_error(parser, "Unexpected end of input");
658
32
    }
659
660
26.7k
    return NJS_DONE;
661
26.7k
}
662
663
664
static njs_int_t
665
njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type,
666
    njs_bool_t init_this)
667
191k
{
668
191k
    njs_variable_t                   *var;
669
191k
    njs_parser_scope_t               *scope, *parent;
670
191k
    const njs_lexer_keyword_entry_t  *keyword;
671
672
191k
    static const njs_str_t  njs_this_str = njs_str("this");
673
674
191k
    scope = njs_mp_zalloc(parser->vm->mem_pool, sizeof(njs_parser_scope_t));
675
191k
    if (njs_slow_path(scope == NULL)) {
676
0
        return NJS_ERROR;
677
0
    }
678
679
191k
    scope->type = type;
680
681
191k
    njs_rbtree_init(&scope->variables, njs_parser_scope_rbtree_compare);
682
191k
    njs_rbtree_init(&scope->labels, njs_parser_scope_rbtree_compare);
683
191k
    njs_rbtree_init(&scope->references, njs_parser_scope_rbtree_compare);
684
685
191k
    parent = parser->scope;
686
191k
    scope->parent = parent;
687
191k
    parser->scope = scope;
688
689
191k
    if (type == NJS_SCOPE_FUNCTION || type == NJS_SCOPE_GLOBAL) {
690
133k
        if (init_this) {
691
            /* Add this as first variable. */
692
107k
            keyword = njs_lexer_keyword(njs_this_str.start,
693
107k
                                        njs_this_str.length);
694
107k
            if (njs_slow_path(keyword == NULL)) {
695
0
                return NJS_ERROR;
696
0
            }
697
698
107k
            var = njs_variable_add(parser, scope, (uintptr_t) keyword->value,
699
107k
                                   NJS_VARIABLE_VAR);
700
107k
            if (njs_slow_path(var == NULL)) {
701
0
                return NJS_ERROR;
702
0
            }
703
704
107k
            var->index = njs_scope_index(type, 0, NJS_LEVEL_LOCAL,
705
107k
                                         NJS_VARIABLE_VAR);
706
107k
        }
707
133k
    }
708
709
191k
    scope->items = 1;
710
711
191k
    return NJS_OK;
712
191k
}
713
714
715
static void
716
njs_parser_scope_end(njs_parser_t *parser)
717
67.9k
{
718
67.9k
    njs_parser_scope_t  *scope, *parent;
719
720
67.9k
    scope = parser->scope;
721
722
67.9k
    parent = scope->parent;
723
67.9k
    parser->scope = parent;
724
67.9k
}
725
726
727
intptr_t
728
njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1,
729
    njs_rbtree_node_t *node2)
730
7.78M
{
731
7.78M
    njs_variable_node_t  *lex_node1, *lex_node2;
732
733
7.78M
    lex_node1 = (njs_variable_node_t *) node1;
734
7.78M
    lex_node2 = (njs_variable_node_t *) node2;
735
736
7.78M
    if (lex_node1->key < lex_node2->key) {
737
1.88M
        return -1;
738
1.88M
    }
739
740
5.89M
    if (lex_node1->key > lex_node2->key) {
741
4.83M
        return 1;
742
4.83M
    }
743
744
1.06M
    return 0;
745
5.89M
}
746
747
748
static njs_int_t
749
njs_parser_generator_expression(njs_parser_t *parser, njs_lexer_token_t *token,
750
    njs_queue_link_t *current)
751
0
{
752
0
    return njs_parser_not_supported(parser, token);
753
0
}
754
755
756
static njs_int_t
757
njs_parser_class_expression(njs_parser_t *parser, njs_lexer_token_t *token,
758
    njs_queue_link_t *current)
759
0
{
760
0
    return njs_parser_not_supported(parser, token);
761
0
}
762
763
764
static njs_int_t
765
njs_parser_async_generator_expression(njs_parser_t *parser,
766
    njs_lexer_token_t *token, njs_queue_link_t *current)
767
0
{
768
0
    return njs_parser_not_supported(parser, token);
769
0
}
770
771
772
static njs_int_t
773
njs_parser_generator_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
774
    njs_queue_link_t *current)
775
0
{
776
0
    return njs_parser_not_supported(parser, token);
777
0
}
778
779
780
static njs_int_t
781
njs_parser_class_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
782
    njs_queue_link_t *current)
783
0
{
784
0
    return njs_parser_not_supported(parser, token);
785
0
}
786
787
788
static njs_int_t
789
njs_parser_function_or_generator_handler(njs_parser_t *parser,
790
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t is_async)
791
1.57k
{
792
1.57k
    njs_parser_node_t  *node, *cur;
793
794
1.57k
    cur = parser->node;
795
796
1.57k
    if (token->type == NJS_TOKEN_MULTIPLICATION) {
797
0
        njs_lexer_consume_token(parser->lexer, 1);
798
0
        njs_parser_next(parser, njs_parser_generator_declaration);
799
800
1.57k
    } else {
801
1.57k
        if (is_async) {
802
7
            node = njs_parser_node_new(parser,
803
7
                                       NJS_TOKEN_ASYNC_FUNCTION_DECLARATION);
804
1.56k
        } else {
805
1.56k
            node = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_DECLARATION);
806
1.56k
        }
807
808
1.57k
        if (node == NULL) {
809
0
            return NJS_ERROR;
810
0
        }
811
812
1.57k
        node->token_line = token->line;
813
1.57k
        parser->node = node;
814
815
1.57k
        njs_lexer_consume_token(parser->lexer, 1);
816
1.57k
        njs_parser_next(parser, njs_parser_function_declaration);
817
1.57k
    }
818
819
1.57k
    return njs_parser_after(parser, current, cur, 1,
820
1.57k
                            njs_parser_statement_after);
821
1.57k
}
822
823
824
static njs_int_t
825
njs_parser_function_or_generator(njs_parser_t *parser,
826
    njs_lexer_token_t *token, njs_queue_link_t *current)
827
675k
{
828
675k
    if (token->type != NJS_TOKEN_FUNCTION) {
829
673k
        return NJS_DECLINED;
830
673k
    }
831
832
1.56k
    return njs_parser_function_or_generator_handler(parser, token, current, 0);
833
675k
}
834
835
836
static njs_int_t
837
njs_parser_async_function_or_generator(njs_parser_t *parser,
838
    njs_lexer_token_t *token, njs_queue_link_t *current)
839
673k
{
840
673k
    if (token->type != NJS_TOKEN_ASYNC) {
841
673k
        return NJS_DECLINED;
842
673k
    }
843
844
7
    token = njs_lexer_peek_token(parser->lexer, token, 1);
845
7
    if (token == NULL) {
846
0
        return NJS_ERROR;
847
0
    }
848
849
7
    if (token->type != NJS_TOKEN_FUNCTION) {
850
0
        return NJS_DECLINED;
851
0
    }
852
853
7
    njs_lexer_consume_token(parser->lexer, 1);
854
855
7
    return njs_parser_function_or_generator_handler(parser, token, current, 1);
856
7
}
857
858
859
njs_inline njs_int_t
860
njs_parser_expect_semicolon(njs_parser_t *parser, njs_lexer_token_t *token)
861
470k
{
862
470k
    if (token->type != NJS_TOKEN_SEMICOLON) {
863
401k
        if (parser->strict_semicolon
864
401k
            || (token->type != NJS_TOKEN_END
865
401k
                && token->type != NJS_TOKEN_CLOSE_BRACE
866
401k
                && parser->lexer->prev_type != NJS_TOKEN_LINE_END))
867
3.33k
        {
868
3.33k
            return NJS_DECLINED;
869
3.33k
        }
870
871
397k
        return NJS_OK;
872
401k
    }
873
874
69.4k
    njs_lexer_consume_token(parser->lexer, 1);
875
876
69.4k
    return NJS_OK;
877
470k
}
878
879
880
static njs_int_t
881
njs_parser_semicolon(njs_parser_t *parser, njs_lexer_token_t *token,
882
    njs_queue_link_t *current)
883
13.9k
{
884
13.9k
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
885
1
        return njs_parser_failed(parser);
886
1
    }
887
888
13.9k
    return njs_parser_stack_pop(parser);
889
13.9k
}
890
891
892
static njs_int_t
893
njs_parser_close_bracked(njs_parser_t *parser, njs_lexer_token_t *token,
894
    njs_queue_link_t *current)
895
0
{
896
0
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
897
0
        return njs_parser_failed(parser);
898
0
    }
899
900
0
    njs_lexer_consume_token(parser->lexer, 1);
901
902
0
    return njs_parser_stack_pop(parser);
903
0
}
904
905
906
static njs_int_t
907
njs_parser_close_parenthesis(njs_parser_t *parser, njs_lexer_token_t *token,
908
    njs_queue_link_t *current)
909
19.2k
{
910
19.2k
    if (parser->ret != NJS_OK) {
911
868
        return njs_parser_failed(parser);
912
868
    }
913
914
18.3k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
915
6
        return njs_parser_failed(parser);
916
6
    }
917
918
18.3k
    njs_lexer_consume_token(parser->lexer, 1);
919
920
18.3k
    return njs_parser_stack_pop(parser);
921
18.3k
}
922
923
924
static njs_int_t
925
njs_parser_expression_parenthesis(njs_parser_t *parser,
926
    njs_lexer_token_t *token, njs_queue_link_t *current)
927
938
{
928
938
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
929
0
        return njs_parser_failed(parser);
930
0
    }
931
932
938
    njs_lexer_consume_token(parser->lexer, 1);
933
934
938
    parser->node = NULL;
935
936
938
    njs_parser_next(parser, njs_parser_expression);
937
938
938
    return njs_parser_after(parser, current, NULL, 0,
939
938
                            njs_parser_close_parenthesis);
940
938
}
941
942
943
static njs_int_t
944
njs_parser_iteration_statement_for_end(njs_parser_t *parser,
945
    njs_lexer_token_t *token, njs_queue_link_t *current)
946
5.44k
{
947
5.44k
    parser->node->token_line = (uint32_t) (uintptr_t) parser->target;
948
5.44k
    parser->target = NULL;
949
950
5.44k
    njs_parser_scope_end(parser);
951
952
5.44k
    return njs_parser_stack_pop(parser);
953
5.44k
}
954
955
956
/*
957
 * 12.2 Primary Expression.
958
 */
959
static njs_int_t
960
njs_parser_primary_expression_test(njs_parser_t *parser,
961
    njs_lexer_token_t *token, njs_queue_link_t *current)
962
2.69M
{
963
2.69M
    njs_int_t          ret;
964
2.69M
    njs_lexer_token_t  *next;
965
2.69M
    njs_parser_node_t  *node;
966
967
2.69M
    switch (token->type) {
968
    /* IdentifierReference */
969
1.99k
    case NJS_TOKEN_THIS:
970
2.76k
    case NJS_TOKEN_NULL:
971
822k
    case NJS_TOKEN_NAME:
972
826k
    case NJS_TOKEN_YIELD:
973
826k
    case NJS_TOKEN_AWAIT:
974
826k
        goto reference;
975
976
1.09k
    case NJS_TOKEN_TRUE:
977
1.09k
        node = njs_parser_node_new(parser, token->type);
978
1.09k
        if (node == NULL) {
979
0
            return NJS_ERROR;
980
0
        }
981
982
1.09k
        node->u.value = njs_value_true;
983
1.09k
        node->token_line = token->line;
984
985
1.09k
        parser->node = node;
986
1.09k
        goto done;
987
988
10.1k
    case NJS_TOKEN_FALSE:
989
10.1k
        node = njs_parser_node_new(parser, token->type);
990
10.1k
        if (node == NULL) {
991
0
            return NJS_ERROR;
992
0
        }
993
994
10.1k
        node->u.value = njs_value_false;
995
10.1k
        node->token_line = token->line;
996
997
10.1k
        parser->node = node;
998
10.1k
        goto done;
999
1000
1.61M
    case NJS_TOKEN_NUMBER:
1001
1.61M
        node = njs_parser_node_new(parser, NJS_TOKEN_NUMBER);
1002
1.61M
        if (node == NULL) {
1003
0
            return NJS_ERROR;
1004
0
        }
1005
1006
1.61M
        njs_set_number(&node->u.value, token->number);
1007
1.61M
        node->token_line = token->line;
1008
1009
1.61M
        parser->node = node;
1010
1.61M
        goto done;
1011
1012
14.8k
    case NJS_TOKEN_STRING:
1013
14.8k
        node = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1014
14.8k
        if (node == NULL) {
1015
0
            return NJS_ERROR;
1016
0
        }
1017
1018
14.8k
        node->token_line = token->line;
1019
1020
14.8k
        ret = njs_parser_string_create(parser->vm, token, &node->u.value);
1021
14.8k
        if (ret != NJS_OK) {
1022
0
            return NJS_ERROR;
1023
0
        }
1024
1025
14.8k
        parser->node = node;
1026
14.8k
        goto done;
1027
1028
964
    case NJS_TOKEN_ESCAPE_STRING:
1029
        /* Internal optimization. This is not in the specification. */
1030
1031
964
        node = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1032
964
        if (node == NULL) {
1033
0
            return NJS_ERROR;
1034
0
        }
1035
1036
964
        node->token_line = token->line;
1037
1038
964
        ret = njs_parser_escape_string_create(parser, token, &node->u.value);
1039
964
        if (ret != NJS_TOKEN_STRING) {
1040
0
            return NJS_ERROR;
1041
0
        }
1042
1043
964
        parser->node = node;
1044
964
        goto done;
1045
1046
1
    case NJS_TOKEN_UNTERMINATED_STRING:
1047
        /* Internal optimization. This is not in the specification. */
1048
1049
1
        njs_parser_syntax_error(parser, "Unterminated string \"%V\"",
1050
1
                                &token->text);
1051
1
        return NJS_ERROR;
1052
1053
    /* ArrayLiteral */
1054
32.2k
    case NJS_TOKEN_OPEN_BRACKET:
1055
32.2k
        node = njs_parser_node_new(parser, NJS_TOKEN_ARRAY);
1056
32.2k
        if (node == NULL) {
1057
0
            return NJS_ERROR;
1058
0
        }
1059
1060
32.2k
        node->token_line = token->line;
1061
32.2k
        parser->node = node;
1062
1063
32.2k
        njs_parser_next(parser, njs_parser_array_literal);
1064
32.2k
        break;
1065
1066
    /* ObjectLiteral */
1067
17.8k
    case NJS_TOKEN_OPEN_BRACE:
1068
17.8k
        node = njs_parser_node_new(parser, NJS_TOKEN_OBJECT);
1069
17.8k
        if (node == NULL) {
1070
0
            return NJS_ERROR;
1071
0
        }
1072
1073
17.8k
        node->token_line = token->line;
1074
17.8k
        parser->node = node;
1075
1076
17.8k
        njs_parser_next(parser, njs_parser_object_literal);
1077
17.8k
        break;
1078
1079
    /* FunctionExpression */
1080
52.6k
    case NJS_TOKEN_FUNCTION:
1081
52.6k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
1082
52.6k
        if (token == NULL) {
1083
0
            return NJS_ERROR;
1084
0
        }
1085
1086
        /* GeneratorExpression */
1087
52.6k
        if (token->type == NJS_TOKEN_MULTIPLICATION) {
1088
0
            njs_parser_next(parser, njs_parser_generator_expression);
1089
1090
52.6k
        } else {
1091
52.6k
            node = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_EXPRESSION);
1092
52.6k
            if (node == NULL) {
1093
0
                return NJS_ERROR;
1094
0
            }
1095
1096
52.6k
            node->token_line = token->line;
1097
52.6k
            parser->node = node;
1098
1099
52.6k
            njs_parser_next(parser, njs_parser_function_expression);
1100
52.6k
        }
1101
1102
52.6k
        break;
1103
1104
    /* ClassExpression */
1105
52.6k
    case NJS_TOKEN_CLASS:
1106
0
        njs_parser_next(parser, njs_parser_class_expression);
1107
0
        return NJS_OK;
1108
1109
    /* AsyncFunctionExpression */
1110
0
    case NJS_TOKEN_ASYNC:
1111
0
        next = njs_lexer_peek_token(parser->lexer, token, 1);
1112
0
        if (next == NULL) {
1113
0
            return NJS_ERROR;
1114
0
        }
1115
1116
0
        if (next->type != NJS_TOKEN_FUNCTION) {
1117
0
            goto reference;
1118
0
        }
1119
1120
0
        njs_lexer_consume_token(parser->lexer, 1);
1121
1122
0
        next = njs_lexer_peek_token(parser->lexer, next, 0);
1123
0
        if (njs_slow_path(next == NULL)) {
1124
0
            return NJS_ERROR;
1125
0
        }
1126
1127
        /* GeneratorExpression */
1128
0
        if (next->type == NJS_TOKEN_MULTIPLICATION) {
1129
0
            njs_parser_next(parser, njs_parser_async_generator_expression);
1130
1131
0
        } else {
1132
0
            node = njs_parser_node_new(parser,
1133
0
                                       NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION);
1134
0
            if (node == NULL) {
1135
0
                return NJS_ERROR;
1136
0
            }
1137
1138
0
            node->token_line = next->line;
1139
0
            parser->node = node;
1140
1141
0
            njs_parser_next(parser, njs_parser_function_expression);
1142
0
        }
1143
1144
0
        break;
1145
1146
    /* RegularExpressionLiteral */
1147
28.0k
    case NJS_TOKEN_DIVISION:
1148
28.0k
    case NJS_TOKEN_DIVISION_ASSIGNMENT:
1149
28.0k
        node = njs_parser_node_new(parser, NJS_TOKEN_REGEXP);
1150
28.0k
        if (node == NULL) {
1151
0
            return NJS_ERROR;
1152
0
        }
1153
1154
28.0k
        node->token_line = token->line;
1155
28.0k
        parser->node = node;
1156
1157
28.0k
        ret = njs_parser_regexp_literal(parser, token, current);
1158
28.0k
        if (ret != NJS_OK) {
1159
2.76k
            return NJS_ERROR;
1160
2.76k
        }
1161
1162
25.2k
        goto done;
1163
1164
    /* TemplateLiteral */
1165
25.2k
    case NJS_TOKEN_GRAVE:
1166
14.9k
        node = njs_parser_node_new(parser, NJS_TOKEN_TEMPLATE_LITERAL);
1167
14.9k
        if (node == NULL) {
1168
0
            return NJS_ERROR;
1169
0
        }
1170
1171
14.9k
        node->token_line = token->line;
1172
14.9k
        parser->node = node;
1173
1174
14.9k
        njs_parser_next(parser, njs_parser_template_literal);
1175
14.9k
        return NJS_OK;
1176
1177
    /* CoverParenthesizedExpressionAndArrowParameterList */
1178
69.1k
    case NJS_TOKEN_OPEN_PARENTHESIS:
1179
69.1k
        njs_lexer_consume_token(parser->lexer, 1);
1180
1181
        /* TODO: By specification. */
1182
69.1k
        (void) njs_parser_cover_parenthesized_expression;
1183
1184
69.1k
        parser->node = NULL;
1185
1186
69.1k
        njs_parser_next(parser, njs_parser_expression);
1187
1188
69.1k
        return njs_parser_after(parser, current, NULL, 0,
1189
14.9k
                                njs_parser_close_parenthesis);
1190
1191
9.49k
    default:
1192
9.49k
        if (njs_lexer_token_is_identifier_reference(token)) {
1193
1.35k
            goto reference;
1194
1.35k
        }
1195
1196
8.13k
        return njs_parser_reject(parser);
1197
2.69M
    }
1198
1199
102k
    njs_lexer_consume_token(parser->lexer, 1);
1200
1201
102k
    return NJS_OK;
1202
1203
827k
reference:
1204
1205
827k
    node = njs_parser_reference(parser, token);
1206
827k
    if (node == NULL) {
1207
0
        return NJS_ERROR;
1208
0
    }
1209
1210
827k
    node->token_line = token->line;
1211
827k
    parser->node = node;
1212
1213
2.49M
done:
1214
1215
2.49M
    njs_lexer_consume_token(parser->lexer, 1);
1216
1217
2.49M
    return NJS_DONE;
1218
827k
}
1219
1220
1221
static njs_int_t
1222
njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1223
    njs_queue_link_t *current)
1224
28.0k
{
1225
28.0k
    u_char                *p;
1226
28.0k
    njs_str_t             text;
1227
28.0k
    njs_int_t             ret;
1228
28.0k
    njs_lexer_t           *lexer;
1229
28.0k
    njs_value_t           *value, retval;
1230
28.0k
    njs_regex_flags_t     flags;
1231
28.0k
    njs_regexp_pattern_t  *pattern;
1232
1233
28.0k
    static const njs_value_t  string_message = njs_string("message");
1234
1235
28.0k
    value = &parser->node->u.value;
1236
28.0k
    lexer = parser->lexer;
1237
1238
28.0k
    if (token->type == NJS_TOKEN_DIVISION_ASSIGNMENT) {
1239
0
        lexer->start--;
1240
0
    }
1241
1242
6.19M
    for (p = lexer->start; p < lexer->end; p++) {
1243
1244
6.19M
        switch (*p) {
1245
4
        case '\n':
1246
5
        case '\r':
1247
5
            goto failed;
1248
1249
7.64k
        case '[':
1250
133k
            while (1) {
1251
133k
                if (++p >= lexer->end) {
1252
0
                    goto failed;
1253
0
                }
1254
1255
133k
                if (*p == ']') {
1256
7.64k
                    break;
1257
7.64k
                }
1258
1259
125k
                switch (*p) {
1260
0
                case '\n':
1261
0
                case '\r':
1262
0
                    goto failed;
1263
1264
2.09k
                case '\\':
1265
2.09k
                    if (++p >= lexer->end || *p == '\n' || *p == '\r') {
1266
0
                        goto failed;
1267
0
                    }
1268
1269
2.09k
                    break;
1270
125k
                }
1271
125k
            }
1272
1273
7.64k
            break;
1274
1275
13.2k
        case '\\':
1276
13.2k
            if (++p >= lexer->end || *p == '\n' || *p == '\r') {
1277
1
                goto failed;
1278
1
            }
1279
1280
13.2k
            break;
1281
1282
27.9k
        case '/':
1283
27.9k
            text.start = lexer->start;
1284
27.9k
            text.length = p - text.start;
1285
27.9k
            p++;
1286
27.9k
            lexer->start = p;
1287
1288
27.9k
            flags = njs_regexp_flags(&p, lexer->end);
1289
1290
27.9k
            if (njs_slow_path(flags < 0)) {
1291
1
                njs_parser_syntax_error(parser, "Invalid RegExp flags \"%*s\"",
1292
1
                                        p - lexer->start, lexer->start);
1293
1294
1
                return NJS_ERROR;
1295
1
            }
1296
1297
27.9k
            lexer->start = p;
1298
1299
27.9k
            pattern = njs_regexp_pattern_create(parser->vm, text.start,
1300
27.9k
                                                text.length, flags);
1301
1302
27.9k
            if (njs_slow_path(pattern == NULL)) {
1303
2.72k
                retval = njs_vm_exception(parser->vm);
1304
2.72k
                ret = njs_value_property(parser->vm, &retval,
1305
2.72k
                                         njs_value_arg(&string_message),
1306
2.72k
                                         &retval);
1307
2.72k
                if (njs_slow_path(ret != NJS_OK)) {
1308
0
                    return NJS_ERROR;
1309
0
                }
1310
1311
2.72k
                njs_string_get(&retval, &text);
1312
1313
2.72k
                njs_parser_syntax_error(parser, "%V", &text);
1314
1315
2.72k
                return NJS_ERROR;
1316
2.72k
            }
1317
1318
25.2k
            value->data.u.data = pattern;
1319
1320
25.2k
            return NJS_OK;
1321
6.19M
        }
1322
6.19M
    }
1323
1324
38
failed:
1325
1326
38
    njs_parser_syntax_error(parser, "Unterminated RegExp \"%*s\"",
1327
38
                            p - (lexer->start - 1), lexer->start - 1);
1328
38
    return NJS_ERROR;
1329
28.0k
}
1330
1331
1332
static njs_int_t
1333
njs_parser_template_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1334
    njs_queue_link_t *current)
1335
1.27M
{
1336
1.27M
    njs_index_t        index;
1337
1.27M
    njs_parser_node_t  *node, *array, *template, *temp;
1338
1339
1.27M
    temp = njs_parser_node_new(parser, 0);
1340
1.27M
    if (temp == NULL) {
1341
0
        return NJS_ERROR;
1342
0
    }
1343
1344
1.27M
    array = njs_parser_node_new(parser, NJS_TOKEN_ARRAY);
1345
1.27M
    if (array == NULL) {
1346
0
        return NJS_ERROR;
1347
0
    }
1348
1349
1.27M
    array->token_line = token->line;
1350
1351
1.27M
    template = parser->node;
1352
1353
1.27M
    index = njs_scope_temp_index(template->scope);
1354
1.27M
    if (njs_slow_path(index == NJS_INDEX_ERROR)) {
1355
0
        return NJS_ERROR;
1356
0
    }
1357
1358
1.27M
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1359
1.26M
        node = njs_parser_argument(parser, array, index);
1360
1.26M
        if (node == NULL) {
1361
0
            return NJS_ERROR;
1362
0
        }
1363
1364
1.26M
        node->temporary = 1;
1365
1366
1.26M
        template->right = node;
1367
1.26M
        temp->right = node;
1368
1369
1.26M
        index = njs_scope_temp_index(template->scope);
1370
1.26M
        if (njs_slow_path(index == NJS_INDEX_ERROR)) {
1371
0
            return NJS_ERROR;
1372
0
        }
1373
1374
1.26M
    } else {
1375
14.9k
        template->left = array;
1376
14.9k
        temp->right = template;
1377
14.9k
    }
1378
1379
1.27M
    temp->temporary = 1;
1380
1.27M
    temp->left = template;
1381
1.27M
    temp->index = index;
1382
1383
1.27M
    parser->target = temp;
1384
1385
1.27M
    token->text.start++;
1386
1.27M
    token->text.length = 0;
1387
1388
1.27M
    njs_parser_next(parser, njs_parser_template_literal_string);
1389
1390
1.27M
    return NJS_OK;
1391
1.27M
}
1392
1393
1394
static njs_int_t
1395
njs_parser_template_literal_string(njs_parser_t *parser,
1396
    njs_lexer_token_t *token, njs_queue_link_t *current)
1397
1.28M
{
1398
1.28M
    njs_int_t          ret, ret_item;
1399
1.28M
    njs_parser_node_t  *template;
1400
1401
1.28M
    template = parser->target->left;
1402
1403
1.28M
    ret = njs_parser_template_string(parser, token);
1404
1.28M
    if (ret == NJS_ERROR) {
1405
20
        njs_parser_syntax_error(parser, "Unterminated template literal");
1406
20
        return NJS_DONE;
1407
20
    }
1408
1409
1.28M
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1410
1.26M
        ret_item = njs_parser_array_item(parser, template->right->left,
1411
1.26M
                                         parser->node);
1412
1413
1.26M
    } else {
1414
18.3k
        ret_item = njs_parser_array_item(parser, template->left, parser->node);
1415
18.3k
    }
1416
1417
1.28M
    if (ret_item != NJS_OK) {
1418
0
        return NJS_ERROR;
1419
0
    }
1420
1421
1.28M
    if (ret == NJS_DONE) {
1422
1.27M
        parser->node = template;
1423
1424
1.27M
        njs_parser_node_free(parser, parser->target);
1425
1.27M
        njs_lexer_consume_token(parser->lexer, 1);
1426
1427
1.27M
        return njs_parser_stack_pop(parser);
1428
1.27M
    }
1429
1430
7.80k
    parser->node = NULL;
1431
1432
7.80k
    njs_parser_next(parser, njs_parser_expression);
1433
1434
7.80k
    njs_lexer_consume_token(parser->lexer, 1);
1435
1436
7.80k
    return njs_parser_after(parser, current, parser->target, 0,
1437
1.28M
                            njs_parser_template_literal_expression);
1438
1.28M
}
1439
1440
1441
static njs_int_t
1442
njs_parser_template_literal_expression(njs_parser_t *parser,
1443
    njs_lexer_token_t *token, njs_queue_link_t *current)
1444
6.76k
{
1445
6.76k
    njs_int_t          ret;
1446
6.76k
    njs_parser_node_t  *template, *node, *parent;
1447
1448
6.76k
    if (parser->ret != NJS_OK) {
1449
3
        return njs_parser_failed(parser);
1450
3
    }
1451
1452
6.75k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
1453
10
        njs_parser_syntax_error(parser, "Missing \"}\" in template expression");
1454
10
        return NJS_DONE;
1455
10
    }
1456
1457
6.74k
    parent = parser->target->right;
1458
6.74k
    template = parser->target->left;
1459
1460
6.74k
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1461
3.37k
        node = njs_parser_argument(parser, parser->node, parser->target->index);
1462
3.37k
        if (node == NULL) {
1463
0
            return NJS_ERROR;
1464
0
        }
1465
1466
3.37k
        parent->right = node;
1467
3.37k
        parent = node;
1468
1469
3.37k
        parser->target->index = njs_scope_temp_index(node->scope);
1470
3.37k
        if (njs_slow_path(parser->target->index == NJS_INDEX_ERROR)) {
1471
0
            return NJS_ERROR;
1472
0
        }
1473
1474
3.37k
    } else {
1475
3.37k
        ret = njs_parser_array_item(parser, template->left, parser->node);
1476
3.37k
        if (ret != NJS_OK) {
1477
0
            return NJS_ERROR;
1478
0
        }
1479
3.37k
    }
1480
1481
6.74k
    parser->target->right = parent;
1482
1483
6.74k
    parser->node = NULL;
1484
1485
6.74k
    njs_parser_next(parser, njs_parser_template_literal_string);
1486
1487
6.74k
    token->text.length = 0;
1488
6.74k
    token->text.start += 1;
1489
1490
6.74k
    return NJS_OK;
1491
6.74k
}
1492
1493
1494
static njs_int_t
1495
njs_parser_cover_parenthesized_expression(njs_parser_t *parser,
1496
    njs_lexer_token_t *token, njs_queue_link_t *current)
1497
0
{
1498
0
    switch (token->type) {
1499
0
    case NJS_TOKEN_CLOSE_PARENTHESIS:
1500
0
        (void) njs_parser_stack_pop(parser);
1501
0
        break;
1502
1503
0
    case NJS_TOKEN_ELLIPSIS:
1504
0
        njs_parser_next(parser, njs_parser_binding_identifier_pattern);
1505
0
        break;
1506
1507
0
    default:
1508
0
        parser->node = NULL;
1509
1510
0
        njs_parser_next(parser, njs_parser_expression);
1511
1512
0
        return njs_parser_after(parser, current, NULL, 0,
1513
0
                               njs_parser_cover_parenthesized_expression_after);
1514
0
    }
1515
1516
0
    njs_lexer_consume_token(parser->lexer, 1);
1517
1518
0
    return NJS_OK;
1519
0
}
1520
1521
1522
static njs_int_t
1523
njs_parser_binding_identifier_pattern(njs_parser_t *parser,
1524
    njs_lexer_token_t *token, njs_queue_link_t *current)
1525
0
{
1526
    /*
1527
     * BindingIdentifier )
1528
     * BindingPattern )
1529
     */
1530
1531
0
    switch (token->type) {
1532
1533
    /* BindingIdentifier */
1534
0
    case NJS_TOKEN_NAME:
1535
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1536
0
        break;
1537
1538
0
    case NJS_TOKEN_YIELD:
1539
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1540
0
        break;
1541
1542
0
    case NJS_TOKEN_AWAIT:
1543
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1544
0
        break;
1545
1546
    /* BindingPattern */
1547
0
    case NJS_TOKEN_OPEN_BRACKET:
1548
0
        njs_parser_next(parser, njs_parser_array_binding_pattern);
1549
1550
0
        njs_lexer_consume_token(parser->lexer, 1);
1551
0
        return njs_parser_after(parser, current, NULL, 0,
1552
0
                                njs_parser_cover_parenthesized_expression_end);
1553
1554
0
    case NJS_TOKEN_OPEN_BRACE:
1555
0
        njs_parser_next(parser, njs_parser_object_binding_pattern);
1556
1557
0
        njs_lexer_consume_token(parser->lexer, 1);
1558
0
        return njs_parser_after(parser, current, NULL, 0,
1559
0
                                njs_parser_cover_parenthesized_expression_end);
1560
1561
0
    default:
1562
0
        return NJS_ERROR;
1563
0
    }
1564
1565
0
    njs_lexer_consume_token(parser->lexer, 1);
1566
1567
0
    return NJS_OK;
1568
0
}
1569
1570
1571
static njs_int_t
1572
njs_parser_cover_parenthesized_expression_after(njs_parser_t *parser,
1573
    njs_lexer_token_t *token, njs_queue_link_t *current)
1574
0
{
1575
    /*
1576
     * )
1577
     * ,)
1578
     * , ... BindingIdentifier )
1579
     * , ... BindingPattern )
1580
     */
1581
1582
0
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
1583
0
        goto shift_stack;
1584
0
    }
1585
1586
0
    if (token->type != NJS_TOKEN_COMMA) {
1587
0
        return njs_parser_failed(parser);
1588
0
    }
1589
1590
0
    njs_lexer_consume_token(parser->lexer, 1);
1591
1592
0
    token = njs_lexer_token(parser->lexer, 0);
1593
0
    if (njs_slow_path(token == NULL)) {
1594
0
        return NJS_ERROR;
1595
0
    }
1596
1597
0
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
1598
0
        goto shift_stack;
1599
0
    }
1600
1601
0
    if(token->type != NJS_TOKEN_ELLIPSIS) {
1602
0
        return njs_parser_failed(parser);
1603
0
    }
1604
1605
0
    njs_lexer_consume_token(parser->lexer, 1);
1606
1607
0
    njs_parser_next(parser, njs_parser_binding_identifier_pattern);
1608
1609
0
    return NJS_OK;
1610
1611
0
shift_stack:
1612
1613
0
    njs_lexer_consume_token(parser->lexer, 1);
1614
1615
0
    return njs_parser_stack_pop(parser);
1616
0
}
1617
1618
1619
static njs_int_t
1620
njs_parser_cover_parenthesized_expression_end(njs_parser_t *parser,
1621
    njs_lexer_token_t *token, njs_queue_link_t *current)
1622
0
{
1623
0
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
1624
0
        return njs_parser_failed(parser);
1625
0
    }
1626
1627
0
    njs_lexer_consume_token(parser->lexer, 1);
1628
1629
0
    return njs_parser_stack_pop(parser);
1630
0
}
1631
1632
1633
/*
1634
 * 12.2.5 Array Initializer.
1635
 */
1636
static njs_int_t
1637
njs_parser_array_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1638
    njs_queue_link_t *current)
1639
32.2k
{
1640
32.2k
    parser->target = parser->node;
1641
32.2k
    parser->node = NULL;
1642
1643
32.2k
    njs_parser_next(parser, njs_parser_array_element_list);
1644
1645
32.2k
    return NJS_OK;
1646
32.2k
}
1647
1648
1649
static njs_int_t
1650
njs_parser_array_element_list(njs_parser_t *parser, njs_lexer_token_t *token,
1651
    njs_queue_link_t *current)
1652
1.85M
{
1653
1.85M
    njs_parser_node_t  *array;
1654
1655
1.85M
    array = parser->target;
1656
1657
1.85M
    switch (token->type) {
1658
14.7k
    case NJS_TOKEN_CLOSE_BRACKET:
1659
14.7k
        njs_lexer_consume_token(parser->lexer, 1);
1660
1661
14.7k
        parser->node = array;
1662
1663
14.7k
        return njs_parser_stack_pop(parser);
1664
1665
236k
    case NJS_TOKEN_COMMA:
1666
236k
        njs_lexer_consume_token(parser->lexer, 1);
1667
1668
236k
        array->ctor = 1;
1669
236k
        array->u.length++;
1670
1671
236k
        return NJS_OK;
1672
1673
0
    case NJS_TOKEN_ELLIPSIS:
1674
#if 0
1675
        njs_lexer_consume_token(parser->lexer, 1);
1676
1677
        njs_parser_next(parser, njs_parser_assignment_expression);
1678
1679
        return njs_parser_after(parser, current, array, 0,
1680
                                njs_parser_array_spread_element);
1681
#else
1682
0
        (void) njs_parser_array_spread_element;
1683
0
        return njs_parser_failed(parser);
1684
0
#endif
1685
1686
1.60M
    default:
1687
1.60M
        break;
1688
1.85M
    }
1689
1690
1.60M
    njs_parser_next(parser, njs_parser_assignment_expression);
1691
1692
1.60M
    return njs_parser_after(parser, current, array, 0, njs_parser_array_after);
1693
1.85M
}
1694
1695
1696
static njs_int_t
1697
njs_parser_array_after(njs_parser_t *parser, njs_lexer_token_t *token,
1698
    njs_queue_link_t *current)
1699
1.58M
{
1700
1.58M
    njs_int_t  ret;
1701
1702
1.58M
    if (parser->ret != NJS_OK) {
1703
542
        return njs_parser_failed(parser);
1704
542
    }
1705
1706
1.58M
    ret = njs_parser_array_item(parser, parser->target, parser->node);
1707
1.58M
    if (ret != NJS_OK) {
1708
0
        return NJS_ERROR;
1709
0
    }
1710
1711
1.58M
    switch (token->type) {
1712
1.56M
    case NJS_TOKEN_COMMA:
1713
1.56M
        njs_lexer_consume_token(parser->lexer, 1);
1714
1715
        /* Fall through. */
1716
1717
1.58M
    case NJS_TOKEN_CLOSE_BRACKET:
1718
1.58M
        njs_parser_next(parser, njs_parser_array_element_list);
1719
1.58M
        break;
1720
1721
216
    default:
1722
216
        return njs_parser_failed(parser);
1723
1.58M
    }
1724
1725
1.58M
    return NJS_OK;
1726
1.58M
}
1727
1728
1729
static njs_int_t
1730
njs_parser_array_spread_element(njs_parser_t *parser, njs_lexer_token_t *token,
1731
    njs_queue_link_t *current)
1732
0
{
1733
0
    if (parser->ret != NJS_OK || token->type != NJS_TOKEN_CLOSE_BRACKET) {
1734
0
        return njs_parser_failed(parser);
1735
0
    }
1736
1737
0
    njs_lexer_consume_token(parser->lexer, 1);
1738
1739
0
    parser->node = parser->target;
1740
1741
0
    return njs_parser_stack_pop(parser);
1742
0
}
1743
1744
1745
/*
1746
 * 12.2.6 Object Initializer.
1747
 */
1748
static njs_int_t
1749
njs_parser_object_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1750
    njs_queue_link_t *current)
1751
17.8k
{
1752
17.8k
    njs_parser_node_t *node;
1753
1754
17.8k
    node = njs_parser_node_new(parser, 0);
1755
17.8k
    if (node == NULL) {
1756
0
        return NJS_ERROR;
1757
0
    }
1758
1759
17.8k
    node->left = parser->node;
1760
1761
17.8k
    parser->node = NULL;
1762
17.8k
    parser->target = node;
1763
1764
17.8k
    njs_parser_next(parser, njs_parser_property_definition_list);
1765
1766
17.8k
    return njs_parser_after(parser, current, node, 1,
1767
17.8k
                            njs_parser_object_literal_after);
1768
17.8k
}
1769
1770
1771
static njs_int_t
1772
njs_parser_object_literal_after(njs_parser_t *parser, njs_lexer_token_t *token,
1773
    njs_queue_link_t *current)
1774
8.99k
{
1775
8.99k
    if (token->type == NJS_TOKEN_COMMA) {
1776
0
        njs_lexer_consume_token(parser->lexer, 1);
1777
1778
0
        token = njs_lexer_token(parser->lexer, 1);
1779
0
        if (token == NULL) {
1780
0
            return NJS_ERROR;
1781
0
        }
1782
0
    }
1783
1784
8.99k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
1785
1.77k
        return njs_parser_failed(parser);
1786
1.77k
    }
1787
1788
7.22k
    njs_lexer_consume_token(parser->lexer, 1);
1789
1790
7.22k
    parser->node = parser->target->left;
1791
1792
7.22k
    njs_parser_node_free(parser, parser->target);
1793
7.22k
    parser->target = NULL;
1794
1795
7.22k
    return njs_parser_stack_pop(parser);
1796
8.99k
}
1797
1798
1799
static njs_int_t
1800
njs_parser_property_definition_list(njs_parser_t *parser,
1801
    njs_lexer_token_t *token, njs_queue_link_t *current)
1802
17.8k
{
1803
17.8k
    njs_parser_next(parser, njs_parser_property_definition);
1804
1805
17.8k
    return njs_parser_after(parser, current, parser->target, 1,
1806
17.8k
                            njs_parser_property_definition_list_after);
1807
17.8k
}
1808
1809
1810
static njs_int_t
1811
njs_parser_property_definition_list_after(njs_parser_t *parser,
1812
    njs_lexer_token_t *token, njs_queue_link_t *current)
1813
14.9k
{
1814
14.9k
    if (token->type != NJS_TOKEN_COMMA) {
1815
8.99k
        return njs_parser_stack_pop(parser);
1816
8.99k
    }
1817
1818
5.92k
    njs_lexer_consume_token(parser->lexer, 1);
1819
1820
5.92k
    njs_parser_next(parser, njs_parser_property_definition);
1821
1822
5.92k
    return njs_parser_after(parser, current, parser->target, 1,
1823
14.9k
                            njs_parser_property_definition_list_after);
1824
14.9k
}
1825
1826
1827
njs_inline njs_parser_node_t *
1828
njs_parser_property_name_node(njs_parser_t *parser, njs_lexer_token_t *token)
1829
19.1k
{
1830
19.1k
    njs_int_t          ret;
1831
19.1k
    njs_parser_node_t  *property;
1832
1833
19.1k
    if (token->type == NJS_TOKEN_NUMBER) {
1834
2.65k
        property = njs_parser_node_new(parser, NJS_TOKEN_NUMBER);
1835
2.65k
        if (property != NULL) {
1836
2.65k
             njs_set_number(&property->u.value, token->number);
1837
2.65k
        }
1838
1839
16.5k
    } else if (token->type == NJS_TOKEN_ESCAPE_STRING) {
1840
7.86k
        property = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1841
1842
7.86k
        if (property != NULL) {
1843
7.86k
            ret = njs_parser_escape_string_create(parser, token,
1844
7.86k
                                                  &property->u.value);
1845
7.86k
            if (ret != NJS_TOKEN_STRING) {
1846
7.50k
                return NULL;
1847
7.50k
            }
1848
7.86k
        }
1849
1850
8.67k
    } else {
1851
8.67k
        property = njs_parser_node_string(parser->vm, token, parser);
1852
8.67k
    }
1853
1854
11.6k
    if (property != NULL) {
1855
11.6k
        property->token_line = token->line;
1856
11.6k
    }
1857
1858
11.6k
    return property;
1859
19.1k
}
1860
1861
1862
njs_inline njs_int_t
1863
njs_parser_property_name(njs_parser_t *parser, njs_queue_link_t *current,
1864
    unsigned consume)
1865
8.96k
{
1866
8.96k
    njs_lexer_token_t  *token;
1867
8.96k
    njs_parser_node_t  *property;
1868
1869
8.96k
    if (consume > 1) {
1870
8.90k
        token = njs_lexer_token(parser->lexer, 0);
1871
8.90k
        if (token == NULL) {
1872
0
            return NJS_ERROR;
1873
0
        }
1874
1875
8.90k
        property = njs_parser_property_name_node(parser, token);
1876
8.90k
        if (property == NULL) {
1877
0
            return NJS_ERROR;
1878
0
        }
1879
1880
8.90k
        parser->target->right = property;
1881
8.90k
        parser->target->index = (token->type == NJS_TOKEN_NAME);
1882
8.90k
    }
1883
1884
8.96k
    njs_lexer_consume_token(parser->lexer, consume);
1885
1886
8.96k
    parser->node = NULL;
1887
1888
8.96k
    njs_parser_next(parser, njs_parser_assignment_expression);
1889
1890
8.96k
    return njs_parser_after(parser, current, parser->target, 1,
1891
8.96k
                            njs_parser_property_definition_after);
1892
8.96k
}
1893
1894
1895
static njs_int_t
1896
njs_parser_property_definition_ident(njs_parser_t *parser,
1897
    njs_lexer_token_t *token, njs_parser_node_t *temp)
1898
1.96k
{
1899
1.96k
    temp->right = njs_parser_node_string(parser->vm, token, parser);
1900
1.96k
    if (temp->right == NULL) {
1901
0
        return NJS_ERROR;
1902
0
    }
1903
1904
1.96k
    temp->right->index = NJS_TOKEN_OPEN_BRACKET;
1905
1906
1.96k
    parser->node = njs_parser_reference(parser, token);
1907
1.96k
    if (parser->node == NULL) {
1908
0
        return NJS_ERROR;
1909
0
    }
1910
1911
1.96k
    njs_lexer_consume_token(parser->lexer, 1);
1912
1913
1.96k
    token = njs_lexer_token(parser->lexer, 0);
1914
1.96k
    if (token == NULL) {
1915
0
        return NJS_ERROR;
1916
0
    }
1917
1918
    /* CoverInitializedName */
1919
1.96k
    if (token->type == NJS_TOKEN_ASSIGNMENT) {
1920
0
        return njs_parser_not_supported(parser, token);
1921
0
    }
1922
1923
1.96k
    njs_parser_next(parser, njs_parser_property_definition_after);
1924
1925
1.96k
    return NJS_OK;
1926
1.96k
}
1927
1928
1929
static njs_int_t
1930
njs_parser_property_definition(njs_parser_t *parser, njs_lexer_token_t *token,
1931
    njs_queue_link_t *current)
1932
23.8k
{
1933
23.8k
    njs_str_t          *name;
1934
23.8k
    njs_token_type_t   accessor;
1935
23.8k
    njs_lexer_token_t  *next;
1936
23.8k
    njs_parser_node_t  *temp, *property;
1937
1938
23.8k
    temp = parser->target;
1939
1940
23.8k
    switch (token->type) {
1941
2.17k
    case NJS_TOKEN_CLOSE_BRACE:
1942
2.17k
        return njs_parser_stack_pop(parser);
1943
1944
    /* PropertyName */
1945
991
    case NJS_TOKEN_STRING:
1946
8.85k
    case NJS_TOKEN_ESCAPE_STRING:
1947
10.6k
    case NJS_TOKEN_NUMBER:
1948
10.6k
        next = njs_lexer_peek_token(parser->lexer, token, 0);
1949
10.6k
        if (next == NULL) {
1950
0
            return NJS_ERROR;
1951
0
        }
1952
1953
10.6k
        if (next->type == NJS_TOKEN_COLON) {
1954
1.63k
            return njs_parser_property_name(parser, current, 2);
1955
1956
9.04k
        } else if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
1957
9.04k
            goto method_definition;
1958
9.04k
        }
1959
1960
0
        njs_lexer_consume_token(parser->lexer, 1);
1961
1962
0
        return njs_parser_failed(parser);
1963
1964
    /* ComputedPropertyName */
1965
58
    case NJS_TOKEN_OPEN_BRACKET:
1966
58
        njs_lexer_consume_token(parser->lexer, 1);
1967
1968
58
        njs_parser_next(parser, njs_parser_assignment_expression);
1969
1970
58
        return njs_parser_after(parser, current, temp, 1,
1971
10.6k
                                njs_parser_computed_property_name_after);
1972
1973
0
    case NJS_TOKEN_ELLIPSIS:
1974
0
        return njs_parser_not_supported(parser, token);
1975
1976
29
    case NJS_TOKEN_ASYNC:
1977
29
        token = njs_lexer_peek_token(parser->lexer, token, 0);
1978
29
        if (token == NULL) {
1979
0
            return NJS_ERROR;
1980
0
        }
1981
1982
29
        if (token->type == NJS_TOKEN_OPEN_BRACKET) {
1983
0
            njs_lexer_consume_token(parser->lexer, 2);
1984
1985
0
            njs_parser_next(parser, njs_parser_assignment_expression);
1986
1987
0
            return njs_parser_after(parser, current, temp, 1,
1988
0
                                    njs_parser_computed_property_async_after);
1989
0
        }
1990
1991
29
        if (token->type == NJS_TOKEN_COLON) {
1992
0
            return njs_parser_property_name(parser, current, 2);
1993
0
        }
1994
1995
29
        if (!njs_lexer_token_is_identifier_name(token)) {
1996
0
            return njs_parser_failed(parser);
1997
0
        }
1998
1999
29
        next = njs_lexer_peek_token(parser->lexer, token, 0);
2000
29
        if (next == NULL) {
2001
0
            return NJS_ERROR;
2002
0
        }
2003
2004
29
        if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2005
28
            goto method_definition;
2006
28
        }
2007
2008
1
        njs_lexer_consume_token(parser->lexer, 1);
2009
2010
1
        return njs_parser_failed(parser);
2011
2012
10.8k
    default:
2013
10.8k
        if (!njs_lexer_token_is_identifier_name(token)) {
2014
292
            return njs_parser_reject(parser);
2015
292
        }
2016
2017
10.5k
        next = njs_lexer_peek_token(parser->lexer, token, 0);
2018
10.5k
        if (next == NULL) {
2019
0
            return NJS_ERROR;
2020
0
        }
2021
2022
        /* PropertyName */
2023
10.5k
        if (next->type == NJS_TOKEN_COLON) {
2024
7.27k
            return njs_parser_property_name(parser, current, 2);
2025
2026
        /* MethodDefinition */
2027
7.27k
        } else if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2028
154
            goto method_definition;
2029
2030
3.15k
        } else if (njs_lexer_token_is_reserved(token)) {
2031
0
            njs_lexer_consume_token(parser->lexer, 1);
2032
2033
0
            return njs_parser_failed(parser);
2034
0
        }
2035
2036
3.15k
        name = &token->text;
2037
2038
3.15k
        if (name->length == 3 && (memcmp(name->start, "get", 3) == 0
2039
2.18k
                                  || memcmp(name->start, "set", 3) == 0))
2040
2.03k
        {
2041
2.03k
            accessor = (name->start[0] == 'g') ? NJS_TOKEN_PROPERTY_GETTER
2042
2.03k
                                               : NJS_TOKEN_PROPERTY_SETTER;
2043
2044
2.03k
            temp->right = (njs_parser_node_t *) (uintptr_t) accessor;
2045
2046
2.03k
            njs_parser_next(parser, njs_parser_get_set);
2047
2048
2.03k
            return NJS_OK;
2049
2.03k
        }
2050
2051
1.12k
        return njs_parser_property_definition_ident(parser, token, temp);
2052
23.8k
    }
2053
2054
9.22k
method_definition:
2055
2056
9.22k
    property = njs_parser_property_name_node(parser, token);
2057
9.22k
    if (property == NULL) {
2058
7.50k
        return NJS_ERROR;
2059
7.50k
    }
2060
2061
1.71k
    temp->right = property;
2062
1.71k
    temp->right->index = NJS_TOKEN_OPEN_BRACKET;
2063
2064
1.71k
    njs_parser_next(parser, njs_parser_method_definition);
2065
2066
1.71k
    return njs_parser_after(parser, current, temp, 1,
2067
9.22k
                            njs_parser_property_definition_after);
2068
9.22k
}
2069
2070
2071
static njs_int_t
2072
njs_parser_property_definition_after(njs_parser_t *parser,
2073
    njs_lexer_token_t *token, njs_queue_link_t *current)
2074
11.7k
{
2075
11.7k
    njs_int_t          ret;
2076
11.7k
    njs_str_t          name;
2077
11.7k
    njs_bool_t         proto_init;
2078
11.7k
    njs_parser_node_t  *property, *temp;
2079
2080
11.7k
    static const njs_str_t  proto_string = njs_str("__proto__");
2081
2082
11.7k
    temp = parser->target;
2083
11.7k
    property = temp->right;
2084
2085
11.7k
    proto_init = 0;
2086
2087
11.7k
    if (property->index != NJS_TOKEN_OPEN_BRACKET
2088
11.7k
        && njs_is_string(&property->u.value))
2089
7.69k
    {
2090
7.69k
        njs_string_get(&property->u.value, &name);
2091
2092
7.69k
        if (njs_slow_path(njs_strstr_eq(&name, &proto_string))) {
2093
242
            if (temp->token_type == NJS_TOKEN_PROTO_INIT) {
2094
0
                njs_parser_syntax_error(parser,
2095
0
                                   "Duplicate __proto__ fields are not allowed "
2096
0
                                   "in object literals");
2097
0
                return NJS_ERROR;
2098
0
            }
2099
2100
242
            temp->token_type = NJS_TOKEN_PROTO_INIT;
2101
242
            proto_init = 1;
2102
242
        }
2103
7.69k
    }
2104
2105
11.7k
    if (property->index != 0) {
2106
3.73k
        property->index = 0;
2107
3.73k
    }
2108
2109
11.7k
    ret = njs_parser_object_property(parser, temp->left, property,
2110
11.7k
                                     parser->node, proto_init);
2111
11.7k
    if (ret != NJS_OK) {
2112
0
        return NJS_ERROR;
2113
0
    }
2114
2115
11.7k
    temp->right = NULL;
2116
2117
11.7k
    return njs_parser_stack_pop(parser);
2118
11.7k
}
2119
2120
2121
static njs_int_t
2122
njs_parser_computed_property_name_after(njs_parser_t *parser,
2123
    njs_lexer_token_t *token, njs_queue_link_t *current)
2124
58
{
2125
58
    return njs_parser_computed_property_name_handler(parser, token, current, 0);
2126
58
}
2127
2128
2129
static njs_int_t
2130
njs_parser_computed_property_async_after(njs_parser_t *parser,
2131
    njs_lexer_token_t *token, njs_queue_link_t *current)
2132
0
{
2133
0
    return njs_parser_computed_property_name_handler(parser, token, current, 1);
2134
0
}
2135
2136
2137
static njs_int_t
2138
njs_parser_computed_property_name_handler(njs_parser_t *parser,
2139
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async)
2140
58
{
2141
58
    njs_token_type_t   type;
2142
58
    njs_parser_node_t  *expr, *target;
2143
2144
58
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
2145
0
        return njs_parser_failed(parser);
2146
0
    }
2147
2148
58
    njs_lexer_consume_token(parser->lexer, 1);
2149
2150
58
    token = njs_lexer_token(parser->lexer, 0);
2151
58
    if (token == NULL) {
2152
0
        return NJS_ERROR;
2153
0
    }
2154
2155
58
    target = parser->target;
2156
2157
    /*
2158
     * For further identification.
2159
     * In njs_parser_property_definition_after() index will be reset to zero.
2160
     */
2161
58
    parser->node->index = NJS_TOKEN_OPEN_BRACKET;
2162
2163
58
    target->right = parser->node;
2164
2165
58
    if (!async && token->type == NJS_TOKEN_COLON) {
2166
54
        return njs_parser_property_name(parser, current, 1);
2167
2168
    /* MethodDefinition */
2169
54
    } else if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2170
4
        type = (async) ? NJS_TOKEN_ASYNC_FUNCTION : NJS_TOKEN_FUNCTION;
2171
2172
4
        expr = njs_parser_node_new(parser, type);
2173
4
        if (expr == NULL) {
2174
0
            return NJS_ERROR;
2175
0
        }
2176
2177
4
        expr->token_line = token->line;
2178
2179
4
        parser->node = expr;
2180
2181
4
        njs_lexer_consume_token(parser->lexer, 1);
2182
4
        njs_parser_next(parser, njs_parser_function_lambda);
2183
2184
4
        return njs_parser_after(parser, current, parser->target, 1,
2185
4
                                njs_parser_property_definition_after);
2186
4
    }
2187
2188
0
    return njs_parser_failed(parser);
2189
58
}
2190
2191
2192
static njs_int_t
2193
njs_parser_initializer(njs_parser_t *parser, njs_lexer_token_t *token,
2194
    njs_queue_link_t *current)
2195
6.23k
{
2196
6.23k
    njs_parser_node_t  *node;
2197
2198
6.23k
    if (token->type != NJS_TOKEN_ASSIGNMENT) {
2199
0
        return njs_parser_failed(parser);
2200
0
    }
2201
2202
6.23k
    njs_lexer_consume_token(parser->lexer, 1);
2203
2204
6.23k
    node = parser->node;
2205
2206
6.23k
    parser->node = NULL;
2207
2208
6.23k
    njs_parser_next(parser, njs_parser_assignment_expression);
2209
2210
6.23k
    return njs_parser_after(parser, current, node, 1,
2211
6.23k
                            njs_parser_initializer_after);
2212
6.23k
}
2213
2214
2215
static njs_int_t
2216
njs_parser_initializer_after(njs_parser_t *parser, njs_lexer_token_t *token,
2217
    njs_queue_link_t *current)
2218
17.5k
{
2219
17.5k
    njs_parser_node_t  *stmt;
2220
2221
17.5k
    stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
2222
17.5k
    if (stmt == NULL) {
2223
0
        return NJS_ERROR;
2224
0
    }
2225
2226
17.5k
    stmt->left = NULL;
2227
17.5k
    stmt->right = parser->target;
2228
2229
17.5k
    parser->target->right = parser->node;
2230
17.5k
    parser->node = stmt;
2231
2232
17.5k
    return njs_parser_stack_pop(parser);
2233
17.5k
}
2234
2235
2236
static njs_int_t
2237
njs_parser_initializer_assign(njs_parser_t *parser, njs_token_type_t type)
2238
17.5k
{
2239
17.5k
    njs_parser_node_t  *assign;
2240
2241
17.5k
    assign = njs_parser_node_new(parser, type);
2242
17.5k
    if (assign == NULL) {
2243
0
        return NJS_ERROR;
2244
0
    }
2245
2246
17.5k
    assign->u.operation = NJS_VMCODE_MOVE;
2247
17.5k
    assign->left = parser->node;
2248
2249
    /* assign->right in njs_parser_initializer_after. */
2250
2251
17.5k
    parser->node = assign;
2252
2253
17.5k
    return NJS_OK;
2254
17.5k
}
2255
2256
2257
/*
2258
 * 12.3 Left-Hand-Side Expressions.
2259
 */
2260
static njs_int_t
2261
njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token,
2262
    njs_queue_link_t *current)
2263
3.97M
{
2264
3.97M
    njs_parser_node_t  *node, *prop_node;
2265
2266
    /*
2267
     * [ Expression ]
2268
     * . IdentifierName
2269
     * TemplateLiteral
2270
     */
2271
2272
3.97M
    switch (token->type) {
2273
62.3k
    case NJS_TOKEN_OPEN_BRACKET:
2274
62.3k
        node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
2275
62.3k
        if (node == NULL) {
2276
0
            return NJS_ERROR;
2277
0
        }
2278
2279
62.3k
        node->u.operation = NJS_VMCODE_PROPERTY_GET;
2280
62.3k
        node->left = parser->node;
2281
62.3k
        node->token_line = token->line;
2282
2283
62.3k
        parser->node = NULL;
2284
2285
62.3k
        njs_lexer_consume_token(parser->lexer, 1);
2286
2287
62.3k
        njs_parser_next(parser, njs_parser_expression);
2288
2289
62.3k
        return njs_parser_after(parser, current, node, 1,
2290
62.3k
                                njs_parser_member_expression_bracket);
2291
2292
68.9k
    case NJS_TOKEN_DOT:
2293
68.9k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
2294
68.9k
        if (token == NULL) {
2295
0
            return NJS_ERROR;
2296
0
        }
2297
2298
68.9k
        if (njs_lexer_token_is_identifier_name(token)) {
2299
65.2k
            node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
2300
65.2k
            if (node == NULL) {
2301
0
                return NJS_ERROR;
2302
0
            }
2303
2304
65.2k
            node->u.operation = NJS_VMCODE_PROPERTY_GET;
2305
65.2k
            node->token_line = token->line;
2306
2307
65.2k
            prop_node = njs_parser_node_string(parser->vm, token, parser);
2308
65.2k
            if (prop_node == NULL) {
2309
0
                return NJS_ERROR;
2310
0
            }
2311
2312
65.2k
            prop_node->token_line = token->line;
2313
2314
65.2k
            node->left = parser->node;
2315
65.2k
            node->right = prop_node;
2316
2317
65.2k
            parser->node = node;
2318
2319
65.2k
            njs_lexer_consume_token(parser->lexer, 2);
2320
65.2k
            return NJS_AGAIN;
2321
65.2k
        }
2322
2323
3.65k
        njs_lexer_consume_token(parser->lexer, 1);
2324
2325
3.65k
        return NJS_DECLINED;
2326
2327
1.26M
    case NJS_TOKEN_GRAVE:
2328
1.26M
        node = njs_parser_create_call(parser, parser->node, 0);
2329
1.26M
        if (node == NULL) {
2330
0
            return NJS_ERROR;
2331
0
        }
2332
2333
1.26M
        node->token_line = token->line;
2334
2335
1.26M
        parser->node = node;
2336
2337
1.26M
        njs_parser_next(parser, njs_parser_template_literal);
2338
2339
1.26M
        break;
2340
2341
2.58M
    default:
2342
2.58M
        return NJS_DONE;
2343
3.97M
    }
2344
2345
1.26M
    return NJS_OK;
2346
3.97M
}
2347
2348
2349
static njs_int_t
2350
njs_parser_member_expression(njs_parser_t *parser, njs_lexer_token_t *token,
2351
    njs_queue_link_t *current)
2352
2.69M
{
2353
2.69M
    njs_int_t  ret;
2354
2355
    /*
2356
     * PrimaryExpression
2357
     * MemberExpression [ Expression ]
2358
     * MemberExpression . IdentifierName
2359
     * MemberExpression TemplateLiteral
2360
     * SuperProperty
2361
     * MetaProperty
2362
     * new MemberExpression Arguments
2363
     */
2364
2365
2.69M
    switch (token->type) {
2366
    /* SuperProperty */
2367
0
    case NJS_TOKEN_SUPER:
2368
        /* TODO: By specification. */
2369
0
        (void) njs_parser_super_property;
2370
0
        return njs_parser_not_supported(parser, token);
2371
2372
    /* MetaProperty */
2373
2.31k
    case NJS_TOKEN_IMPORT:
2374
        /* TODO: By specification. */
2375
2.31k
        (void) njs_parser_member_expression_import;
2376
2.31k
        return njs_parser_not_supported(parser, token);
2377
2378
1.16k
    case NJS_TOKEN_NEW:
2379
1.16k
        njs_lexer_consume_token(parser->lexer, 1);
2380
2381
1.16k
        njs_parser_next(parser, njs_parser_member_expression_new);
2382
1.16k
        break;
2383
2384
2.69M
    default:
2385
2.69M
        ret = njs_parser_primary_expression_test(parser, token, current);
2386
2387
2.69M
        if (ret != NJS_OK) {
2388
2.50M
            if (ret == NJS_DONE) {
2389
2.49M
                njs_parser_next(parser, njs_parser_member_expression_next);
2390
2.49M
                return NJS_OK;
2391
2.49M
            }
2392
2393
10.8k
            if (njs_is_error(&parser->vm->exception)) {
2394
2.77k
                return NJS_DONE;
2395
2.77k
            }
2396
2397
8.11k
            return ret;
2398
10.8k
        }
2399
2400
186k
        break;
2401
2.69M
    }
2402
2403
188k
    return njs_parser_after(parser, current, NULL, 1,
2404
2.69M
                            njs_parser_member_expression_next);
2405
2.69M
}
2406
2407
2408
static njs_int_t
2409
njs_parser_member_expression_next(njs_parser_t *parser,
2410
    njs_lexer_token_t *token, njs_queue_link_t *current)
2411
3.94M
{
2412
3.94M
    njs_int_t  ret;
2413
2414
    /*
2415
     * [ Expression ]
2416
     * . IdentifierName
2417
     * TemplateLiteral
2418
     */
2419
2420
3.94M
    ret = njs_parser_property(parser, token, current);
2421
2422
3.94M
    switch (ret) {
2423
60.5k
    case NJS_AGAIN:
2424
60.5k
        return NJS_OK;
2425
2426
2.56M
    case NJS_DONE:
2427
2.56M
        return njs_parser_stack_pop(parser);
2428
2429
0
    case NJS_DECLINED:
2430
0
        return njs_parser_failed(parser);
2431
2432
1.31M
    default:
2433
1.31M
        break;
2434
3.94M
    }
2435
2436
1.31M
    return njs_parser_after(parser, current, NULL, 1,
2437
3.94M
                            njs_parser_member_expression_next);
2438
3.94M
}
2439
2440
2441
static njs_int_t
2442
njs_parser_member_expression_bracket(njs_parser_t *parser,
2443
    njs_lexer_token_t *token, njs_queue_link_t *current)
2444
61.0k
{
2445
61.0k
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
2446
709
        return njs_parser_failed(parser);
2447
709
    }
2448
2449
60.3k
    njs_lexer_consume_token(parser->lexer, 1);
2450
2451
60.3k
    parser->target->right = parser->node;
2452
60.3k
    parser->node = parser->target;
2453
2454
60.3k
    return njs_parser_stack_pop(parser);
2455
61.0k
}
2456
2457
2458
static njs_int_t
2459
njs_parser_member_expression_new_next(njs_parser_t *parser,
2460
    njs_lexer_token_t *token, njs_queue_link_t *current)
2461
1.16k
{
2462
1.16k
    njs_int_t  ret;
2463
2464
    /*
2465
     * PrimaryExpression
2466
     * SuperProperty
2467
     * MetaProperty
2468
     * Arguments
2469
     */
2470
2471
1.16k
    switch (token->type) {
2472
    /* SuperProperty */
2473
0
    case NJS_TOKEN_SUPER:
2474
0
        (void) njs_parser_super_property;
2475
0
        return njs_parser_not_supported(parser, token);
2476
2477
    /* MetaProperty */
2478
0
    case NJS_TOKEN_IMPORT:
2479
0
        (void) njs_parser_member_expression_import;
2480
0
        return njs_parser_not_supported(parser, token);
2481
2482
1.16k
    default:
2483
1.16k
        ret = njs_parser_primary_expression_test(parser, token, current);
2484
2485
1.16k
        if (ret != NJS_OK) {
2486
1.11k
            if (ret == NJS_DONE) {
2487
1.11k
                njs_parser_next(parser, njs_parser_member_expression_next);
2488
1.11k
                return NJS_OK;
2489
1.11k
            }
2490
2491
1
            return ret;
2492
1.11k
        }
2493
2494
53
        return njs_parser_after(parser, current, NULL, 1,
2495
1.16k
                                njs_parser_member_expression_next);
2496
1.16k
    }
2497
1.16k
}
2498
2499
2500
static njs_int_t
2501
njs_parser_super_property(njs_parser_t *parser, njs_lexer_token_t *token,
2502
    njs_queue_link_t *current)
2503
0
{
2504
    /*
2505
     * [ Expression ]
2506
     * . IdentifierName
2507
     */
2508
2509
0
    if (token->type == NJS_TOKEN_OPEN_BRACKET) {
2510
0
        parser->node = NULL;
2511
2512
0
        njs_parser_next(parser, njs_parser_expression);
2513
2514
0
        return njs_parser_after(parser, current, NULL, 1,
2515
0
                                njs_parser_close_bracked);
2516
0
    }
2517
2518
0
    if (token->type != NJS_TOKEN_DOT) {
2519
0
        return njs_parser_failed(parser);
2520
0
    }
2521
2522
0
    njs_lexer_consume_token(parser->lexer, 1);
2523
2524
0
    token = njs_lexer_token(parser->lexer, 0);
2525
0
    if (token == NULL) {
2526
0
        return NJS_ERROR;
2527
0
    }
2528
2529
0
    if (!njs_lexer_token_is_identifier_name(token)) {
2530
0
        return njs_parser_failed(parser);
2531
0
    }
2532
2533
0
    return njs_parser_stack_pop(parser);
2534
0
}
2535
2536
2537
static njs_int_t
2538
njs_parser_member_expression_import(njs_parser_t *parser,
2539
    njs_lexer_token_t *token, njs_queue_link_t *current)
2540
0
{
2541
    /*
2542
     * import . meta
2543
     */
2544
2545
0
    if (token->type != NJS_TOKEN_DOT) {
2546
0
        return njs_parser_failed(parser);
2547
0
    }
2548
2549
0
    njs_lexer_consume_token(parser->lexer, 1);
2550
2551
0
    token = njs_lexer_token(parser->lexer, 0);
2552
0
    if (token == NULL) {
2553
0
        return NJS_ERROR;
2554
0
    }
2555
2556
0
    if (token->type != NJS_TOKEN_META) {
2557
0
        return njs_parser_failed(parser);
2558
0
    }
2559
2560
0
    njs_lexer_consume_token(parser->lexer, 1);
2561
2562
0
    return njs_parser_stack_pop(parser);
2563
0
}
2564
2565
2566
static njs_int_t
2567
njs_parser_member_expression_new(njs_parser_t *parser,
2568
    njs_lexer_token_t *token, njs_queue_link_t *current)
2569
1.16k
{
2570
    /*
2571
     * new MemberExpression Arguments
2572
     * new . target
2573
     */
2574
2575
1.16k
    if (token->type != NJS_TOKEN_DOT) {
2576
1.16k
        njs_parser_next(parser, njs_parser_member_expression_new_next);
2577
2578
1.16k
        return njs_parser_after(parser, current, NULL, 1,
2579
1.16k
                                njs_parser_member_expression_new_after);
2580
1.16k
    }
2581
2582
    /* njs_lexer_consume_token(parser->lexer, 1); */
2583
2584
0
    token = njs_lexer_token(parser->lexer, 0);
2585
0
    if (token == NULL) {
2586
0
        return NJS_ERROR;
2587
0
    }
2588
2589
0
    if (token->type != NJS_TOKEN_TARGET) {
2590
0
        return njs_parser_failed(parser);
2591
0
    }
2592
2593
    /* njs_lexer_consume_token(parser->lexer, 1); */
2594
2595
    /* return njs_parser_stack_pop(parser); */
2596
0
    return njs_parser_not_supported(parser, token);
2597
0
}
2598
2599
2600
static njs_int_t
2601
njs_parser_member_expression_new_after(njs_parser_t *parser,
2602
    njs_lexer_token_t *token, njs_queue_link_t *current)
2603
1.16k
{
2604
1.16k
    njs_parser_node_t  *func;
2605
2606
1.16k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
2607
66
        parser->node = njs_parser_create_call(parser, parser->node, 1);
2608
66
        if (parser->node == NULL) {
2609
0
            return NJS_ERROR;
2610
0
        }
2611
2612
66
        parser->node->token_line = token->line;
2613
2614
66
        return njs_parser_stack_pop(parser);
2615
66
    }
2616
2617
1.10k
    func = njs_parser_create_call(parser, parser->node, 1);
2618
1.10k
    if (func == NULL) {
2619
0
        return NJS_ERROR;
2620
0
    }
2621
2622
1.10k
    func->token_line = token->line;
2623
1.10k
    parser->node = func;
2624
2625
1.10k
    njs_lexer_consume_token(parser->lexer, 1);
2626
1.10k
    njs_parser_next(parser, njs_parser_arguments);
2627
2628
1.10k
    return njs_parser_after(parser, current, func, 1,
2629
1.10k
                            njs_parser_member_expression_new_args);
2630
1.10k
}
2631
2632
2633
static njs_int_t
2634
njs_parser_member_expression_new_args(njs_parser_t *parser,
2635
    njs_lexer_token_t *token, njs_queue_link_t *current)
2636
1.07k
{
2637
1.07k
    parser->node = parser->target;
2638
2639
1.07k
    return njs_parser_stack_pop(parser);
2640
1.07k
}
2641
2642
2643
static njs_parser_node_t *
2644
njs_parser_create_call(njs_parser_t *parser, njs_parser_node_t *node,
2645
    uint8_t ctor)
2646
1.28M
{
2647
1.28M
    njs_parser_node_t  *func;
2648
2649
1.28M
    switch (node->token_type) {
2650
10.4k
    case NJS_TOKEN_NAME:
2651
10.4k
        func = node;
2652
10.4k
        func->token_type = NJS_TOKEN_FUNCTION_CALL;
2653
2654
10.4k
        break;
2655
2656
12.9k
    case NJS_TOKEN_PROPERTY:
2657
12.9k
        func = njs_parser_node_new(parser, NJS_TOKEN_METHOD_CALL);
2658
12.9k
        if (func == NULL) {
2659
0
            return NULL;
2660
0
        }
2661
2662
12.9k
        func->left = node;
2663
12.9k
        break;
2664
2665
1.26M
    default:
2666
        /*
2667
         * NJS_TOKEN_METHOD_CALL,
2668
         * NJS_TOKEN_FUNCTION_CALL,
2669
         * NJS_TOKEN_FUNCTION_EXPRESSION,
2670
         * NJS_TOKEN_OPEN_PARENTHESIS,
2671
         * NJS_TOKEN_EVAL.
2672
         */
2673
1.26M
        func = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_CALL);
2674
1.26M
        if (func == NULL) {
2675
0
            return NULL;
2676
0
        }
2677
2678
1.26M
        func->left = node;
2679
1.26M
        break;
2680
1.28M
    }
2681
2682
1.28M
    func->ctor = ctor;
2683
2684
1.28M
    return func;
2685
1.28M
}
2686
2687
2688
static njs_int_t
2689
njs_parser_call_expression(njs_parser_t *parser, njs_lexer_token_t *token,
2690
    njs_queue_link_t *current)
2691
0
{
2692
0
    njs_int_t  ret;
2693
2694
    /*
2695
     * CoverCallExpressionAndAsyncArrowHead
2696
     * SuperCall
2697
     * ImportCall
2698
     * CallExpression Arguments
2699
     * CallExpression [ Expression ]
2700
     * CallExpression . IdentifierName
2701
     * CallExpression TemplateLiteral
2702
     */
2703
2704
0
    switch (token->type) {
2705
    /* MemberExpression or SuperCall */
2706
0
    case NJS_TOKEN_SUPER:
2707
0
        return njs_parser_not_supported(parser, token);
2708
2709
0
    case NJS_TOKEN_IMPORT:
2710
0
        return njs_parser_not_supported(parser, token);
2711
2712
0
    default:
2713
0
        break;
2714
0
    }
2715
2716
0
    njs_parser_next(parser, njs_parser_member_expression);
2717
2718
0
    ret = njs_parser_after(parser, current, NULL, 1,
2719
0
                           njs_parser_call_expression_args);
2720
0
    if (ret != NJS_OK) {
2721
0
        return NJS_ERROR;
2722
0
    }
2723
2724
0
    return njs_parser_after(parser, current, NULL, 1,
2725
0
                            njs_parser_call_expression_after);
2726
0
}
2727
2728
2729
static njs_int_t
2730
njs_parser_call_expression_args(njs_parser_t *parser, njs_lexer_token_t *token,
2731
    njs_queue_link_t *current)
2732
0
{
2733
0
    njs_parser_node_t  *func;
2734
2735
0
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
2736
0
        return njs_parser_failed(parser);
2737
0
    }
2738
2739
0
    func = njs_parser_create_call(parser, parser->node, 0);
2740
0
    if (func == NULL) {
2741
0
        return NJS_ERROR;
2742
0
    }
2743
2744
0
    func->token_line = token->line;
2745
0
    parser->node = func;
2746
2747
0
    njs_lexer_consume_token(parser->lexer, 1);
2748
0
    njs_parser_next(parser, njs_parser_arguments);
2749
2750
0
    return njs_parser_after(parser, current, func, 1,
2751
0
                            njs_parser_left_hand_side_expression_node);
2752
0
}
2753
2754
2755
static njs_int_t
2756
njs_parser_call_expression_after(njs_parser_t *parser,
2757
    njs_lexer_token_t *token, njs_queue_link_t *current)
2758
0
{
2759
0
    njs_int_t          ret;
2760
0
    njs_parser_node_t  *func;
2761
2762
    /*
2763
     * Arguments
2764
     * [ Expression ]
2765
     * . IdentifierName
2766
     * TemplateLiteral
2767
     */
2768
2769
0
    switch (token->type) {
2770
0
    case NJS_TOKEN_OPEN_PARENTHESIS:
2771
0
        func = njs_parser_create_call(parser, parser->node, 0);
2772
0
        if (func == NULL) {
2773
0
            return NJS_ERROR;
2774
0
        }
2775
2776
0
        func->token_line = token->line;
2777
0
        parser->node = func;
2778
2779
0
        njs_lexer_consume_token(parser->lexer, 1);
2780
0
        njs_parser_next(parser, njs_parser_arguments);
2781
2782
0
        ret = njs_parser_after(parser, current, func, 1,
2783
0
                               njs_parser_left_hand_side_expression_node);
2784
0
        if (ret != NJS_OK) {
2785
0
            return NJS_ERROR;
2786
0
        }
2787
2788
0
        break;
2789
2790
0
    default:
2791
0
        ret = njs_parser_property(parser, token, current);
2792
2793
0
        switch (ret) {
2794
0
        case NJS_AGAIN:
2795
0
            return NJS_OK;
2796
2797
0
        case NJS_DONE:
2798
0
            return njs_parser_stack_pop(parser);
2799
2800
0
        case NJS_DECLINED:
2801
0
            return njs_parser_failed(parser);
2802
2803
0
        default:
2804
0
            break;
2805
0
        }
2806
2807
0
        break;
2808
0
    }
2809
2810
0
    return njs_parser_after(parser, current, NULL, 1,
2811
0
                            njs_parser_call_expression_after);
2812
0
}
2813
2814
2815
static njs_int_t
2816
njs_parser_arguments(njs_parser_t *parser, njs_lexer_token_t *token,
2817
    njs_queue_link_t *current)
2818
24.2k
{
2819
    /*
2820
     * )
2821
     * ArgumentList )
2822
     * ArgumentList , )
2823
     */
2824
2825
24.2k
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
2826
5.09k
        njs_lexer_consume_token(parser->lexer, 1);
2827
5.09k
        return njs_parser_stack_pop(parser);
2828
5.09k
    }
2829
2830
19.1k
    parser->scope->in_args = 1;
2831
2832
19.1k
    njs_parser_next(parser, njs_parser_argument_list);
2833
2834
19.1k
    return njs_parser_after(parser, current, NULL, 1,
2835
24.2k
                            njs_parser_parenthesis_or_comma);
2836
24.2k
}
2837
2838
2839
static njs_int_t
2840
njs_parser_parenthesis_or_comma(njs_parser_t *parser, njs_lexer_token_t *token,
2841
    njs_queue_link_t *current)
2842
16.9k
{
2843
16.9k
    parser->scope->in_args = 0;
2844
2845
16.9k
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
2846
16.9k
        njs_lexer_consume_token(parser->lexer, 1);
2847
16.9k
        return njs_parser_stack_pop(parser);
2848
16.9k
    }
2849
2850
26
    if (token->type != NJS_TOKEN_COMMA) {
2851
26
        return njs_parser_failed(parser);
2852
26
    }
2853
2854
0
    njs_lexer_consume_token(parser->lexer, 1);
2855
2856
0
    token = njs_lexer_token(parser->lexer, 0);
2857
0
    if (njs_slow_path(token == NULL)) {
2858
0
        return NJS_ERROR;
2859
0
    }
2860
2861
0
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
2862
0
        return njs_parser_failed(parser);
2863
0
    }
2864
2865
0
    njs_lexer_consume_token(parser->lexer, 1);
2866
2867
0
    return njs_parser_stack_pop(parser);
2868
0
}
2869
2870
2871
static njs_int_t
2872
njs_parser_argument_list(njs_parser_t *parser, njs_lexer_token_t *token,
2873
    njs_queue_link_t *current)
2874
28.8k
{
2875
    /*
2876
     * AssignmentExpression
2877
     * ... AssignmentExpression
2878
     * ArgumentList , AssignmentExpression
2879
     * ArgumentList , ... AssignmentExpression
2880
     */
2881
2882
#if 0 /* TODO. */
2883
    if (token->type == NJS_TOKEN_ELLIPSIS) {
2884
        njs_lexer_consume_token(parser->lexer, 1);
2885
    }
2886
#endif
2887
2888
28.8k
    njs_parser_next(parser, njs_parser_assignment_expression);
2889
2890
28.8k
    return njs_parser_after(parser, current, parser->node, 1,
2891
28.8k
                            njs_parser_argument_list_after);
2892
28.8k
}
2893
2894
2895
static njs_int_t
2896
njs_parser_argument_list_after(njs_parser_t *parser, njs_lexer_token_t *token,
2897
    njs_queue_link_t *current)
2898
26.6k
{
2899
26.6k
    njs_parser_node_t  *node;
2900
2901
26.6k
    node = njs_parser_node_new(parser, NJS_TOKEN_ARGUMENT);
2902
26.6k
    if (node == NULL) {
2903
0
        return NJS_ERROR;
2904
0
    }
2905
2906
26.6k
    node->index = njs_scope_temp_index(node->scope);
2907
26.6k
    if (njs_slow_path(node->index == NJS_INDEX_ERROR)) {
2908
0
        return NJS_ERROR;
2909
0
    }
2910
2911
26.6k
    node->token_line = token->line;
2912
26.6k
    node->left = parser->node;
2913
2914
26.6k
    parser->node->dest = node;
2915
26.6k
    parser->target->right = node;
2916
26.6k
    parser->node = node;
2917
2918
26.6k
    if (token->type == NJS_TOKEN_COMMA) {
2919
9.68k
        njs_lexer_consume_token(parser->lexer, 1);
2920
2921
9.68k
        token = njs_lexer_token(parser->lexer, 0);
2922
9.68k
        if (token == NULL) {
2923
0
            return NJS_ERROR;
2924
0
        }
2925
2926
9.68k
        if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
2927
27
            return njs_parser_stack_pop(parser);
2928
27
        }
2929
2930
9.65k
        return njs_parser_argument_list(parser, token, current);
2931
9.68k
    }
2932
2933
16.9k
    return njs_parser_stack_pop(parser);
2934
26.6k
}
2935
2936
2937
static njs_int_t
2938
njs_parser_optional_expression_after(njs_parser_t *parser,
2939
    njs_lexer_token_t *token, njs_queue_link_t *current)
2940
11.5k
{
2941
11.5k
    if (token->type != NJS_TOKEN_CONDITIONAL) {
2942
0
        return njs_parser_stack_pop(parser);
2943
0
    }
2944
2945
11.5k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
2946
11.5k
    if (token == NULL) {
2947
0
        return NJS_ERROR;
2948
0
    }
2949
2950
11.5k
    if (token->type != NJS_TOKEN_DOT) {
2951
10.5k
        return njs_parser_stack_pop(parser);
2952
10.5k
    }
2953
2954
1.02k
    njs_parser_next(parser, njs_parser_optional_chain);
2955
2956
1.02k
    return njs_parser_after(parser, current, NULL, 1,
2957
11.5k
                            njs_parser_optional_expression_after);
2958
11.5k
}
2959
2960
2961
static njs_int_t
2962
njs_parser_optional_chain(njs_parser_t *parser, njs_lexer_token_t *token,
2963
    njs_queue_link_t *current)
2964
2.05k
{
2965
2.05k
    njs_int_t          ret;
2966
2.05k
    njs_parser_node_t  *func;
2967
2968
    /*
2969
     * ? . Arguments
2970
     * ? . [ Expression ]
2971
     * ? . IdentifierName
2972
     * ? . TemplateLiteral
2973
     * OptionalChain Arguments
2974
     * OptionalChain [ Expression ]
2975
     * OptionalChain . IdentifierName
2976
     * OptionalChain TemplateLiteral
2977
     */
2978
2979
2.05k
    if (token->type != NJS_TOKEN_CONDITIONAL) {
2980
1.02k
        return njs_parser_failed(parser);
2981
1.02k
    }
2982
2983
1.02k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
2984
1.02k
    if (token == NULL) {
2985
0
        return NJS_ERROR;
2986
0
    }
2987
2988
1.02k
    if (token->type != NJS_TOKEN_DOT) {
2989
0
        return njs_parser_failed(parser);
2990
0
    }
2991
2992
1.02k
    njs_lexer_consume_token(parser->lexer, 1);
2993
2994
1.02k
    token = njs_lexer_token(parser->lexer, 0);
2995
1.02k
    if (token == NULL) {
2996
0
        return NJS_ERROR;
2997
0
    }
2998
2999
1.02k
    switch (token->type) {
3000
0
    case NJS_TOKEN_OPEN_PARENTHESIS:
3001
0
        func = njs_parser_create_call(parser, parser->node, 0);
3002
0
        if (func == NULL) {
3003
0
            return NJS_ERROR;
3004
0
        }
3005
3006
0
        func->token_line = token->line;
3007
0
        parser->node = func;
3008
3009
0
        njs_lexer_consume_token(parser->lexer, 2);
3010
0
        njs_parser_next(parser, njs_parser_arguments);
3011
3012
0
        ret = njs_parser_after(parser, current, func, 1,
3013
0
                               njs_parser_left_hand_side_expression_node);
3014
0
        if (ret != NJS_OK) {
3015
0
            return NJS_ERROR;
3016
0
        }
3017
3018
0
        break;
3019
3020
1.02k
    default:
3021
1.02k
        ret = njs_parser_property(parser, token, current);
3022
3023
1.02k
        switch (ret) {
3024
0
        case NJS_DONE:
3025
0
        case NJS_DECLINED:
3026
0
            return njs_parser_failed(parser);
3027
3028
1.02k
        default:
3029
1.02k
            break;
3030
1.02k
        }
3031
3032
1.02k
        break;
3033
1.02k
    }
3034
3035
1.02k
    return njs_parser_after(parser, current, NULL, 1,
3036
1.02k
                            njs_parser_optional_chain_after);
3037
1.02k
}
3038
3039
3040
static njs_int_t
3041
njs_parser_optional_chain_after(njs_parser_t *parser, njs_lexer_token_t *token,
3042
    njs_queue_link_t *current)
3043
28.6k
{
3044
28.6k
    njs_int_t          ret;
3045
28.6k
    njs_parser_node_t  *func;
3046
3047
    /*
3048
     * OptionalChain Arguments
3049
     * OptionalChain [ Expression ]
3050
     * OptionalChain . IdentifierName
3051
     * OptionalChain TemplateLiteral
3052
     */
3053
3054
28.6k
    switch (token->type) {
3055
4.15k
    case NJS_TOKEN_OPEN_PARENTHESIS:
3056
4.15k
        func = njs_parser_create_call(parser, parser->node, 0);
3057
4.15k
        if (func == NULL) {
3058
0
            return NJS_ERROR;
3059
0
        }
3060
3061
4.15k
        func->token_line = token->line;
3062
4.15k
        parser->node = func;
3063
3064
4.15k
        njs_lexer_consume_token(parser->lexer, 1);
3065
4.15k
        njs_parser_next(parser, njs_parser_arguments);
3066
3067
4.15k
        ret = njs_parser_after(parser, current, func, 1,
3068
4.15k
                               njs_parser_left_hand_side_expression_node);
3069
4.15k
        if (ret != NJS_OK) {
3070
0
            return NJS_ERROR;
3071
0
        }
3072
3073
4.15k
        break;
3074
3075
24.5k
    default:
3076
24.5k
        ret = njs_parser_property(parser, token, current);
3077
3078
24.5k
        switch (ret) {
3079
3.69k
        case NJS_AGAIN:
3080
3.69k
            return NJS_OK;
3081
3082
13.1k
        case NJS_DONE:
3083
13.1k
            return njs_parser_stack_pop(parser);
3084
3085
3.65k
        case NJS_DECLINED:
3086
3.65k
            return njs_parser_failed(parser);
3087
3088
3.99k
        default:
3089
3.99k
            break;
3090
24.5k
        }
3091
3092
3.99k
        break;
3093
28.6k
    }
3094
3095
8.15k
    return njs_parser_after(parser, current, NULL, 1,
3096
28.6k
                            njs_parser_optional_chain_after);
3097
28.6k
}
3098
3099
3100
static njs_int_t
3101
njs_parser_new_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3102
    njs_queue_link_t *current)
3103
273
{
3104
273
    if (token->type != NJS_TOKEN_NEW) {
3105
4
        parser->node = NULL;
3106
3107
4
        njs_parser_next(parser, njs_parser_member_expression_new);
3108
3109
4
        return NJS_OK;
3110
4
    }
3111
3112
269
    njs_lexer_consume_token(parser->lexer, 1);
3113
3114
269
    return njs_parser_after(parser, current, NULL, 1,
3115
273
                            njs_parser_new_expression_after);
3116
273
}
3117
3118
3119
static njs_int_t
3120
njs_parser_new_expression_after(njs_parser_t *parser, njs_lexer_token_t *token,
3121
    njs_queue_link_t *current)
3122
153
{
3123
153
    njs_parser_node_t  *func;
3124
3125
153
    if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
3126
0
        njs_parser_next(parser, njs_parser_member_expression_new_after);
3127
0
        return NJS_OK;
3128
0
    }
3129
3130
153
    func = njs_parser_create_call(parser, parser->node, 1);
3131
153
    if (func == NULL) {
3132
0
        return NJS_ERROR;
3133
0
    }
3134
3135
153
    func->token_line = token->line;
3136
153
    parser->node = func;
3137
3138
153
    return njs_parser_stack_pop(parser);
3139
153
}
3140
3141
3142
static njs_int_t
3143
njs_parser_left_hand_side_expression(njs_parser_t *parser,
3144
    njs_lexer_token_t *token, njs_queue_link_t *current)
3145
2.69M
{
3146
    /*
3147
     * NewExpression = new MemberExpression
3148
     * CallExpression = MemberExpression Arguments
3149
     * OptionalExpression = MemberExpression OptionalChain
3150
     */
3151
3152
2.69M
    switch (token->type) {
3153
    /* NewExpression or MemberExpression */
3154
1.16k
    case NJS_TOKEN_NEW:
3155
1.16k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
3156
1.16k
        if (token == NULL) {
3157
0
            return NJS_ERROR;
3158
0
        }
3159
3160
1.16k
        if (token->type == NJS_TOKEN_NEW) {
3161
4
            njs_lexer_consume_token(parser->lexer, 1);
3162
3163
4
            njs_parser_next(parser, njs_parser_new_expression);
3164
3165
4
            return njs_parser_after(parser, current, NULL, 1,
3166
4
                                    njs_parser_left_hand_side_expression_after);
3167
4
        }
3168
3169
1.16k
        break;
3170
3171
    /* CallExpression or MemberExpression */
3172
1.16k
    case NJS_TOKEN_SUPER:
3173
2.31k
    case NJS_TOKEN_IMPORT:
3174
2.31k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
3175
2.31k
        if (token == NULL) {
3176
0
            return NJS_ERROR;
3177
0
        }
3178
3179
2.31k
        if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
3180
0
            njs_parser_next(parser, njs_parser_call_expression);
3181
0
            return NJS_OK;
3182
0
        }
3183
3184
2.31k
        break;
3185
3186
2.69M
    default:
3187
2.69M
        break;
3188
2.69M
    }
3189
3190
2.69M
    njs_parser_next(parser, njs_parser_member_expression);
3191
3192
2.69M
    return njs_parser_after(parser, current, NULL, 1,
3193
2.69M
                            njs_parser_left_hand_side_expression_after);
3194
2.69M
}
3195
3196
3197
static njs_int_t
3198
njs_parser_left_hand_side_expression_after(njs_parser_t *parser,
3199
    njs_lexer_token_t *token, njs_queue_link_t *current)
3200
2.56M
{
3201
2.56M
    njs_int_t          ret;
3202
2.56M
    njs_parser_node_t  *func;
3203
3204
2.56M
    switch (token->type) {
3205
    /* CallExpression */
3206
19.0k
    case NJS_TOKEN_OPEN_PARENTHESIS:
3207
19.0k
        func = njs_parser_create_call(parser, parser->node, 0);
3208
19.0k
        if (func == NULL) {
3209
0
            return NJS_ERROR;
3210
0
        }
3211
3212
19.0k
        func->token_line = token->line;
3213
19.0k
        parser->node = func;
3214
3215
19.0k
        njs_lexer_consume_token(parser->lexer, 1);
3216
19.0k
        njs_parser_next(parser, njs_parser_arguments);
3217
3218
19.0k
        ret = njs_parser_after(parser, current, func, 1,
3219
19.0k
                               njs_parser_left_hand_side_expression_node);
3220
19.0k
        if (ret != NJS_OK) {
3221
0
            return NJS_ERROR;
3222
0
        }
3223
3224
19.0k
        return njs_parser_after(parser, current, NULL, 1,
3225
19.0k
                                njs_parser_left_hand_side_expression_optional);
3226
3227
    /* OptionalExpression */
3228
11.5k
    case NJS_TOKEN_CONDITIONAL:
3229
11.5k
        njs_parser_next(parser, njs_parser_optional_expression_after);
3230
11.5k
        break;
3231
3232
2.53M
    default:
3233
2.53M
        return njs_parser_stack_pop(parser);
3234
2.56M
    }
3235
3236
11.5k
    return NJS_OK;
3237
2.56M
}
3238
3239
3240
static njs_int_t
3241
njs_parser_left_hand_side_expression_node(njs_parser_t *parser,
3242
    njs_lexer_token_t *token, njs_queue_link_t *current)
3243
20.9k
{
3244
20.9k
    parser->node = parser->target;
3245
3246
20.9k
    return njs_parser_stack_pop(parser);
3247
20.9k
}
3248
3249
3250
static njs_int_t
3251
njs_parser_left_hand_side_expression_optional(njs_parser_t *parser,
3252
    njs_lexer_token_t *token, njs_queue_link_t *current)
3253
16.8k
{
3254
    /* OptionalExpression */
3255
16.8k
    if (token->type == NJS_TOKEN_CONDITIONAL) {
3256
0
        njs_parser_next(parser, njs_parser_optional_expression_after);
3257
0
        return NJS_OK;
3258
0
    }
3259
3260
16.8k
    njs_parser_next(parser, njs_parser_optional_chain_after);
3261
3262
16.8k
    return NJS_OK;
3263
16.8k
}
3264
3265
3266
static njs_int_t
3267
njs_parser_expression_node(njs_parser_t *parser, njs_lexer_token_t *token,
3268
    njs_queue_link_t *current, njs_token_type_t type,
3269
    njs_vmcode_operation_t operation, njs_parser_state_func_t after)
3270
12.4M
{
3271
12.4M
    njs_parser_node_t  *node;
3272
3273
12.4M
    if (parser->target != NULL) {
3274
37.6k
        parser->target->right = parser->node;
3275
37.6k
        parser->target->right->dest = parser->target;
3276
37.6k
        parser->node = parser->target;
3277
37.6k
    }
3278
3279
12.4M
    if (token->type != type) {
3280
12.3M
        return njs_parser_stack_pop(parser);
3281
12.3M
    }
3282
3283
45.6k
    node = njs_parser_node_new(parser, type);
3284
45.6k
    if (node == NULL) {
3285
0
        return NJS_ERROR;
3286
0
    }
3287
3288
45.6k
    node->token_line = token->line;
3289
45.6k
    node->u.operation = operation;
3290
45.6k
    node->left = parser->node;
3291
45.6k
    node->left->dest = node;
3292
3293
45.6k
    njs_lexer_consume_token(parser->lexer, 1);
3294
3295
45.6k
    return njs_parser_after(parser, current, node, 1, after);
3296
45.6k
}
3297
3298
3299
/*
3300
 * 12.4 Update Expressions.
3301
 */
3302
static njs_int_t
3303
njs_parser_update_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3304
    njs_queue_link_t *current)
3305
2.69M
{
3306
2.69M
    njs_parser_node_t       *node;
3307
2.69M
    njs_vmcode_operation_t  operation;
3308
3309
2.69M
    switch (token->type) {
3310
2.23k
    case NJS_TOKEN_INCREMENT:
3311
2.23k
        operation = NJS_VMCODE_INCREMENT;
3312
2.23k
        break;
3313
3314
5.57k
    case NJS_TOKEN_DECREMENT:
3315
5.57k
        operation = NJS_VMCODE_DECREMENT;
3316
5.57k
        break;
3317
3318
2.68M
    default:
3319
2.68M
        njs_parser_next(parser, njs_parser_left_hand_side_expression);
3320
3321
2.68M
        return njs_parser_after(parser, current, NULL, 1,
3322
2.69M
                                njs_parser_update_expression_post);
3323
2.69M
    }
3324
3325
7.81k
    node = njs_parser_node_new(parser, token->type);
3326
7.81k
    if (node == NULL) {
3327
0
        return NJS_ERROR;
3328
0
    }
3329
3330
7.81k
    node->token_line = token->line;
3331
7.81k
    node->u.operation = operation;
3332
3333
7.81k
    njs_lexer_consume_token(parser->lexer, 1);
3334
7.81k
    njs_parser_next(parser, njs_parser_left_hand_side_expression);
3335
3336
7.81k
    return njs_parser_after(parser, current, node, 1,
3337
7.81k
                            njs_parser_update_expression_unary);
3338
7.81k
}
3339
3340
3341
static njs_int_t
3342
njs_parser_update_expression_post(njs_parser_t *parser,
3343
    njs_lexer_token_t *token, njs_queue_link_t *current)
3344
2.54M
{
3345
2.54M
    njs_token_type_t        type;
3346
2.54M
    njs_parser_node_t       *node;
3347
2.54M
    njs_vmcode_operation_t  operation;
3348
3349
    /* [no LineTerminator here] */
3350
3351
2.54M
    switch (token->type) {
3352
4.31k
    case NJS_TOKEN_INCREMENT:
3353
4.31k
        type = NJS_TOKEN_POST_INCREMENT;
3354
4.31k
        operation = NJS_VMCODE_POST_INCREMENT;
3355
4.31k
        break;
3356
3357
10.4k
    case NJS_TOKEN_DECREMENT:
3358
10.4k
        type = NJS_TOKEN_POST_DECREMENT;
3359
10.4k
        operation = NJS_VMCODE_POST_DECREMENT;
3360
10.4k
        break;
3361
3362
2.53M
    default:
3363
2.53M
        return njs_parser_stack_pop(parser);
3364
2.54M
    }
3365
3366
14.7k
    if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) {
3367
398
        return njs_parser_stack_pop(parser);
3368
398
    }
3369
3370
14.4k
    if (!njs_parser_is_lvalue(parser->node)) {
3371
0
        njs_lexer_consume_token(parser->lexer, 1);
3372
3373
0
        njs_parser_ref_error(parser,
3374
0
                             "Invalid left-hand side in postfix operation");
3375
0
        return NJS_DONE;
3376
0
    }
3377
3378
14.4k
    node = njs_parser_node_new(parser, type);
3379
14.4k
    if (node == NULL) {
3380
0
        return NJS_ERROR;
3381
0
    }
3382
3383
14.4k
    node->token_line = token->line;
3384
14.4k
    node->u.operation = operation;
3385
14.4k
    node->left = parser->node;
3386
3387
14.4k
    parser->node = node;
3388
3389
14.4k
    njs_lexer_consume_token(parser->lexer, 1);
3390
3391
14.4k
    return njs_parser_stack_pop(parser);
3392
14.4k
}
3393
3394
3395
static njs_int_t
3396
njs_parser_update_expression_unary(njs_parser_t *parser,
3397
    njs_lexer_token_t *token, njs_queue_link_t *current)
3398
7.60k
{
3399
7.60k
    if (!njs_parser_is_lvalue(parser->node)) {
3400
0
        njs_parser_ref_error(parser,
3401
0
                             "Invalid left-hand side in prefix operation");
3402
0
        return NJS_DONE;
3403
0
    }
3404
3405
7.60k
    parser->target->left = parser->node;
3406
7.60k
    parser->node = parser->target;
3407
3408
7.60k
    return njs_parser_stack_pop(parser);
3409
7.60k
}
3410
3411
3412
/*
3413
 * 12.5 Unary Operators.
3414
 */
3415
static njs_int_t
3416
njs_parser_unary_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3417
    njs_queue_link_t *current)
3418
2.73M
{
3419
2.73M
    njs_token_type_t        type;
3420
2.73M
    njs_parser_node_t       *node;
3421
2.73M
    njs_vmcode_operation_t  operation;
3422
3423
2.73M
    switch (token->type) {
3424
372
    case NJS_TOKEN_DELETE:
3425
372
        type = NJS_TOKEN_DELETE;
3426
372
        operation = NJS_VMCODE_DELETE;
3427
372
        break;
3428
3429
541
    case NJS_TOKEN_VOID:
3430
541
        type = NJS_TOKEN_VOID;
3431
541
        operation = NJS_VMCODE_VOID;
3432
541
        break;
3433
3434
8.49k
    case NJS_TOKEN_TYPEOF:
3435
8.49k
        type = NJS_TOKEN_TYPEOF;
3436
8.49k
        operation = NJS_VMCODE_TYPEOF;
3437
8.49k
        break;
3438
3439
18.4k
    case NJS_TOKEN_ADDITION:
3440
18.4k
        type = NJS_TOKEN_UNARY_PLUS;
3441
18.4k
        operation = NJS_VMCODE_UNARY_PLUS;
3442
18.4k
        break;
3443
3444
4.23k
    case NJS_TOKEN_SUBTRACTION:
3445
4.23k
        type = NJS_TOKEN_UNARY_NEGATION;
3446
4.23k
        operation = NJS_VMCODE_UNARY_NEGATION;
3447
4.23k
        break;
3448
3449
5.75k
    case NJS_TOKEN_BITWISE_NOT:
3450
5.75k
        type = NJS_TOKEN_BITWISE_NOT;
3451
5.75k
        operation = NJS_VMCODE_BITWISE_NOT;
3452
5.75k
        break;
3453
3454
1.09k
    case NJS_TOKEN_LOGICAL_NOT:
3455
1.09k
        type = NJS_TOKEN_LOGICAL_NOT;
3456
1.09k
        operation = NJS_VMCODE_LOGICAL_NOT;
3457
1.09k
        break;
3458
3459
    /* AwaitExpression */
3460
2.30k
    case NJS_TOKEN_AWAIT:
3461
2.30k
        njs_parser_next(parser, njs_parser_await);
3462
2.30k
        return NJS_OK;
3463
3464
2.69M
    default:
3465
2.69M
        njs_parser_next(parser, njs_parser_update_expression);
3466
3467
2.69M
        return njs_parser_after(parser, current, parser->target, 1,
3468
2.73M
                                njs_parser_unary_expression_after);
3469
2.73M
    }
3470
3471
38.8k
    node = njs_parser_node_new(parser, type);
3472
38.8k
    if (node == NULL) {
3473
0
        return NJS_ERROR;
3474
0
    }
3475
3476
38.8k
    node->token_line = token->line;
3477
38.8k
    node->u.operation = operation;
3478
3479
38.8k
    parser->target = node;
3480
3481
38.8k
    njs_lexer_consume_token(parser->lexer, 1);
3482
3483
38.8k
    return njs_parser_after(parser, current, node, 1,
3484
38.8k
                            njs_parser_unary_expression_next);
3485
38.8k
}
3486
3487
3488
static njs_int_t
3489
njs_parser_unary_expression_after(njs_parser_t *parser,
3490
    njs_lexer_token_t *token, njs_queue_link_t *current)
3491
2.55M
{
3492
2.55M
    if (parser->target == NULL &&
3493
2.55M
        token->type == NJS_TOKEN_EXPONENTIATION)
3494
31
    {
3495
31
        return njs_parser_exponentiation_expression_match(parser, token,
3496
31
                                                          current);
3497
31
    }
3498
3499
2.55M
    return njs_parser_stack_pop(parser);
3500
2.55M
}
3501
3502
3503
static njs_int_t
3504
njs_parser_unary_expression_next(njs_parser_t *parser,
3505
    njs_lexer_token_t *token, njs_queue_link_t *current)
3506
38.0k
{
3507
38.0k
    double             num;
3508
38.0k
    njs_token_type_t   type;
3509
38.0k
    njs_parser_node_t  *node;
3510
3511
38.0k
    type = parser->target->token_type;
3512
38.0k
    node = parser->node;
3513
3514
38.0k
    if (token->type == NJS_TOKEN_EXPONENTIATION) {
3515
0
        njs_parser_syntax_error(parser, "Either left-hand side or entire "
3516
0
                                "exponentiation must be parenthesized");
3517
0
        return NJS_DONE;
3518
0
    }
3519
3520
38.0k
    if (node->token_type == NJS_TOKEN_NUMBER) {
3521
2.80k
        if (type == NJS_TOKEN_UNARY_PLUS) {
3522
            /* Skip the unary plus of number. */
3523
50
            return njs_parser_stack_pop(parser);
3524
50
        }
3525
3526
2.75k
        if (type == NJS_TOKEN_UNARY_NEGATION) {
3527
            /* Optimization of common negative number. */
3528
2.68k
            num = -njs_number(&node->u.value);
3529
2.68k
            njs_set_number(&node->u.value, num);
3530
3531
2.68k
            return njs_parser_stack_pop(parser);
3532
2.68k
        }
3533
2.75k
    }
3534
3535
35.3k
    if (type == NJS_TOKEN_DELETE) {
3536
372
        switch (node->token_type) {
3537
3538
39
        case NJS_TOKEN_PROPERTY:
3539
39
            node->token_type = NJS_TOKEN_PROPERTY_DELETE;
3540
39
            node->u.operation = NJS_VMCODE_PROPERTY_DELETE;
3541
3542
39
            return njs_parser_stack_pop(parser);
3543
3544
0
        case NJS_TOKEN_NAME:
3545
0
            njs_parser_syntax_error(parser,
3546
0
                                    "Delete of an unqualified identifier");
3547
0
            return NJS_DONE;
3548
3549
333
        default:
3550
333
            break;
3551
372
        }
3552
372
    }
3553
3554
35.2k
    if (type == NJS_TOKEN_TYPEOF && node->token_type == NJS_TOKEN_NAME) {
3555
493
        node->u.reference.type = NJS_TYPEOF;
3556
493
    }
3557
3558
35.2k
    parser->target->left = parser->node;
3559
35.2k
    parser->target->left->dest = parser->target;
3560
35.2k
    parser->node = parser->target;
3561
3562
35.2k
    return njs_parser_stack_pop(parser);
3563
35.3k
}
3564
3565
3566
static njs_int_t
3567
njs_parser_await(njs_parser_t *parser, njs_lexer_token_t *token,
3568
    njs_queue_link_t *current)
3569
2.30k
{
3570
2.30k
    njs_parser_node_t   *node;
3571
3572
2.30k
    if (!njs_function_scope(parser->scope)->async) {
3573
1
        njs_parser_syntax_error(parser,
3574
1
                                "await is only valid in async functions");
3575
1
        return NJS_ERROR;
3576
1
    }
3577
3578
2.30k
    if (parser->scope->in_args) {
3579
0
        njs_parser_syntax_error(parser, "await in arguments not supported");
3580
0
        return NJS_ERROR;
3581
0
    }
3582
3583
2.30k
    node = njs_parser_node_new(parser, NJS_TOKEN_AWAIT);
3584
2.30k
    if (njs_slow_path(node == NULL)) {
3585
0
        return NJS_ERROR;
3586
0
    }
3587
3588
2.30k
    node->token_line = token->line;
3589
3590
2.30k
    njs_lexer_consume_token(parser->lexer, 1);
3591
3592
2.30k
    parser->node = NULL;
3593
3594
2.30k
    njs_parser_next(parser, njs_parser_unary_expression);
3595
3596
2.30k
    return njs_parser_after(parser, current, node, 0,
3597
2.30k
                            njs_parser_await_after);
3598
2.30k
}
3599
3600
3601
static njs_int_t
3602
njs_parser_await_after(njs_parser_t *parser, njs_lexer_token_t *token,
3603
    njs_queue_link_t *current)
3604
2.30k
{
3605
2.30k
    if (parser->ret != NJS_OK) {
3606
0
        return njs_parser_failed(parser);
3607
0
    }
3608
3609
2.30k
    parser->target->right = parser->node;
3610
2.30k
    parser->node = parser->target;
3611
3612
2.30k
    return njs_parser_stack_pop(parser);
3613
2.30k
}
3614
3615
3616
/*
3617
 * 12.6 Exponentiation Operator.
3618
 */
3619
static njs_int_t
3620
njs_parser_exponentiation_expression(njs_parser_t *parser,
3621
    njs_lexer_token_t *token, njs_queue_link_t *current)
3622
2.69M
{
3623
2.69M
    parser->target = NULL;
3624
3625
2.69M
    if (parser->use_lhs == 0) {
3626
2.69M
        njs_parser_next(parser, njs_parser_unary_expression);
3627
3628
        /* For UpdateExpression, see njs_parser_unary_expression_after. */
3629
3630
2.69M
        return NJS_OK;
3631
2.69M
    } else {
3632
1.20k
        parser->use_lhs = 0;
3633
3634
1.20k
        return njs_parser_update_expression_post(parser, token, current);
3635
1.20k
    }
3636
2.69M
}
3637
3638
3639
static njs_int_t
3640
njs_parser_exponentiation_expression_match(njs_parser_t *parser,
3641
    njs_lexer_token_t *token, njs_queue_link_t *current)
3642
62
{
3643
62
    njs_parser_node_t  *node;
3644
3645
62
    if (parser->target != NULL) {
3646
31
        parser->target->right = parser->node;
3647
31
        parser->target->right->dest = parser->target;
3648
31
        parser->node = parser->target;
3649
3650
31
        return njs_parser_stack_pop(parser);
3651
31
    }
3652
3653
31
    if (token->type != NJS_TOKEN_EXPONENTIATION) {
3654
0
        return njs_parser_stack_pop(parser);
3655
0
    }
3656
3657
31
    node = njs_parser_node_new(parser, token->type);
3658
31
    if (node == NULL) {
3659
0
        return NJS_ERROR;
3660
0
    }
3661
3662
31
    node->token_line = token->line;
3663
31
    node->u.operation = NJS_VMCODE_EXPONENTIATION;
3664
31
    node->left = parser->node;
3665
31
    node->left->dest = node;
3666
3667
31
    njs_lexer_consume_token(parser->lexer, 1);
3668
3669
31
    njs_parser_next(parser, njs_parser_exponentiation_expression);
3670
3671
31
    return njs_parser_after(parser, current, node, 1,
3672
31
                            njs_parser_exponentiation_expression_match);
3673
31
}
3674
3675
3676
/*
3677
 * 12.7 Multiplicative Operators.
3678
 */
3679
static njs_int_t
3680
njs_parser_multiplicative_expression(njs_parser_t *parser,
3681
    njs_lexer_token_t *token, njs_queue_link_t *current)
3682
2.61M
{
3683
2.61M
    njs_parser_next(parser, njs_parser_exponentiation_expression);
3684
3685
2.61M
    return njs_parser_after(parser, current, NULL, 1,
3686
2.61M
                            njs_parser_multiplicative_expression_match);
3687
2.61M
}
3688
3689
3690
static njs_int_t
3691
njs_parser_multiplicative_expression_match(njs_parser_t *parser,
3692
    njs_lexer_token_t *token, njs_queue_link_t *current)
3693
2.55M
{
3694
2.55M
    njs_parser_node_t       *node;
3695
2.55M
    njs_vmcode_operation_t  operation;
3696
3697
2.55M
    if (parser->target != NULL) {
3698
62.2k
        parser->target->right = parser->node;
3699
62.2k
        parser->target->right->dest = parser->target;
3700
62.2k
        parser->node = parser->target;
3701
62.2k
    }
3702
3703
2.55M
    switch (token->type) {
3704
8.61k
    case NJS_TOKEN_MULTIPLICATION:
3705
8.61k
        operation = NJS_VMCODE_MULTIPLICATION;
3706
8.61k
        break;
3707
3708
63.6k
    case NJS_TOKEN_DIVISION:
3709
63.6k
        operation = NJS_VMCODE_DIVISION;
3710
63.6k
        break;
3711
3712
2.38k
    case NJS_TOKEN_REMAINDER:
3713
2.38k
        operation = NJS_VMCODE_REMAINDER;
3714
2.38k
        break;
3715
3716
2.48M
    default:
3717
2.48M
        return njs_parser_stack_pop(parser);
3718
2.55M
    }
3719
3720
74.6k
    node = njs_parser_node_new(parser, token->type);
3721
74.6k
    if (node == NULL) {
3722
0
        return NJS_ERROR;
3723
0
    }
3724
3725
74.6k
    node->token_line = token->line;
3726
74.6k
    node->u.operation = operation;
3727
74.6k
    node->left = parser->node;
3728
74.6k
    node->left->dest = node;
3729
3730
74.6k
    njs_lexer_consume_token(parser->lexer, 1);
3731
3732
74.6k
    njs_parser_next(parser, njs_parser_exponentiation_expression);
3733
3734
74.6k
    return njs_parser_after(parser, current, node, 1,
3735
74.6k
                            njs_parser_multiplicative_expression_match);
3736
74.6k
}
3737
3738
3739
/*
3740
 * 12.8 Additive Operators.
3741
 */
3742
static njs_int_t
3743
njs_parser_additive_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3744
    njs_queue_link_t *current)
3745
2.55M
{
3746
2.55M
    njs_parser_next(parser, njs_parser_multiplicative_expression);
3747
3748
2.55M
    return njs_parser_after(parser, current, NULL, 1,
3749
2.55M
                            njs_parser_additive_expression_match);
3750
2.55M
}
3751
3752
3753
static njs_int_t
3754
njs_parser_additive_expression_match(njs_parser_t *parser,
3755
    njs_lexer_token_t *token, njs_queue_link_t *current)
3756
2.48M
{
3757
2.48M
    njs_parser_node_t       *node;
3758
2.48M
    njs_vmcode_operation_t  operation;
3759
3760
2.48M
    if (parser->target != NULL) {
3761
63.5k
        parser->target->right = parser->node;
3762
63.5k
        parser->target->right->dest = parser->target;
3763
63.5k
        parser->node = parser->target;
3764
63.5k
    }
3765
3766
2.48M
    switch (token->type) {
3767
30.6k
    case NJS_TOKEN_ADDITION:
3768
30.6k
        operation = NJS_VMCODE_ADDITION;
3769
30.6k
        break;
3770
3771
35.3k
    case NJS_TOKEN_SUBTRACTION:
3772
35.3k
        operation = NJS_VMCODE_SUBTRACTION;
3773
35.3k
        break;
3774
3775
2.41M
    default:
3776
2.41M
        return njs_parser_stack_pop(parser);
3777
2.48M
    }
3778
3779
65.9k
    node = njs_parser_node_new(parser, token->type);
3780
65.9k
    if (node == NULL) {
3781
0
        return NJS_ERROR;
3782
0
    }
3783
3784
65.9k
    node->token_line = token->line;
3785
65.9k
    node->u.operation = operation;
3786
65.9k
    node->left = parser->node;
3787
65.9k
    node->left->dest = node;
3788
3789
65.9k
    njs_lexer_consume_token(parser->lexer, 1);
3790
3791
65.9k
    njs_parser_next(parser, njs_parser_multiplicative_expression);
3792
3793
65.9k
    return njs_parser_after(parser, current, node, 1,
3794
65.9k
                            njs_parser_additive_expression_match);
3795
65.9k
}
3796
3797
3798
/*
3799
 * 12.9 Bitwise Shift Operators
3800
 */
3801
static njs_int_t
3802
njs_parser_shift_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3803
    njs_queue_link_t *current)
3804
2.55M
{
3805
2.55M
    njs_parser_next(parser, njs_parser_additive_expression);
3806
3807
2.55M
    return njs_parser_after(parser, current, NULL, 1,
3808
2.55M
                            njs_parser_shift_expression_match);
3809
2.55M
}
3810
3811
3812
static njs_int_t
3813
njs_parser_shift_expression_match(njs_parser_t *parser,
3814
    njs_lexer_token_t *token, njs_queue_link_t *current)
3815
2.41M
{
3816
2.41M
    njs_parser_node_t       *node;
3817
2.41M
    njs_vmcode_operation_t  operation;
3818
3819
2.41M
    if (parser->target != NULL) {
3820
2.14k
        parser->target->right = parser->node;
3821
2.14k
        parser->target->right->dest = parser->target;
3822
2.14k
        parser->node = parser->target;
3823
2.14k
    }
3824
3825
2.41M
    switch (token->type) {
3826
482
    case NJS_TOKEN_RIGHT_SHIFT:
3827
482
        operation = NJS_VMCODE_RIGHT_SHIFT;
3828
482
        break;
3829
3830
668
    case NJS_TOKEN_LEFT_SHIFT:
3831
668
        operation = NJS_VMCODE_LEFT_SHIFT;
3832
668
        break;
3833
3834
991
    case NJS_TOKEN_UNSIGNED_RIGHT_SHIFT:
3835
991
        operation = NJS_VMCODE_UNSIGNED_RIGHT_SHIFT;
3836
991
        break;
3837
3838
2.41M
    default:
3839
2.41M
        return njs_parser_stack_pop(parser);
3840
2.41M
    }
3841
3842
2.14k
    node = njs_parser_node_new(parser, token->type);
3843
2.14k
    if (node == NULL) {
3844
0
        return NJS_ERROR;
3845
0
    }
3846
3847
2.14k
    node->token_line = token->line;
3848
2.14k
    node->u.operation = operation;
3849
2.14k
    node->left = parser->node;
3850
2.14k
    node->left->dest = node;
3851
3852
2.14k
    njs_lexer_consume_token(parser->lexer, 1);
3853
3854
2.14k
    njs_parser_next(parser, njs_parser_additive_expression);
3855
3856
2.14k
    return njs_parser_after(parser, current, node, 1,
3857
2.14k
                            njs_parser_shift_expression_match);
3858
2.14k
}
3859
3860
3861
/*
3862
 * 12.10 Relational Operators.
3863
 */
3864
static njs_int_t
3865
njs_parser_relational_expression(njs_parser_t *parser,
3866
    njs_lexer_token_t *token, njs_queue_link_t *current)
3867
2.53M
{
3868
2.53M
    njs_parser_next(parser, njs_parser_shift_expression);
3869
3870
2.53M
    return njs_parser_after(parser, current, NULL, 1,
3871
2.53M
                            njs_parser_relational_expression_match);
3872
2.53M
}
3873
3874
3875
static njs_int_t
3876
njs_parser_relational_expression_match(njs_parser_t *parser,
3877
    njs_lexer_token_t *token, njs_queue_link_t *current)
3878
2.41M
{
3879
2.41M
    njs_parser_node_t       *node;
3880
2.41M
    njs_vmcode_operation_t  operation;
3881
3882
2.41M
    if (parser->target != NULL) {
3883
8.52k
        parser->target->right = parser->node;
3884
8.52k
        parser->target->right->dest = parser->target;
3885
8.52k
        parser->node = parser->target;
3886
8.52k
    }
3887
3888
2.41M
    switch (token->type) {
3889
4.85k
    case NJS_TOKEN_LESS:
3890
4.85k
        operation = NJS_VMCODE_LESS;
3891
4.85k
        break;
3892
3893
2.08k
    case NJS_TOKEN_GREATER:
3894
2.08k
        operation = NJS_VMCODE_GREATER;
3895
2.08k
        break;
3896
3897
547
    case NJS_TOKEN_LESS_OR_EQUAL:
3898
547
        operation = NJS_VMCODE_LESS_OR_EQUAL;
3899
547
        break;
3900
3901
210
    case NJS_TOKEN_GREATER_OR_EQUAL:
3902
210
        operation = NJS_VMCODE_GREATER_OR_EQUAL;
3903
210
        break;
3904
3905
166
    case NJS_TOKEN_INSTANCEOF:
3906
166
        operation = NJS_VMCODE_INSTANCE_OF;
3907
166
        break;
3908
3909
4.97k
    case NJS_TOKEN_IN:
3910
4.97k
        if (njs_lexer_in_fail_get(parser->lexer)) {
3911
624
            njs_parser_syntax_error(parser, "Invalid left-hand side in for-loop");
3912
624
            return NJS_ERROR;
3913
624
        }
3914
4.35k
        operation = NJS_VMCODE_PROPERTY_IN;
3915
4.35k
        break;
3916
3917
2.40M
    default:
3918
2.40M
        return njs_parser_stack_pop(parser);
3919
2.41M
    }
3920
3921
12.2k
    node = njs_parser_node_new(parser, token->type);
3922
12.2k
    if (node == NULL) {
3923
0
        return NJS_ERROR;
3924
0
    }
3925
3926
12.2k
    node->token_line = token->line;
3927
12.2k
    node->u.operation = operation;
3928
12.2k
    node->left = parser->node;
3929
12.2k
    node->left->dest = node;
3930
3931
12.2k
    njs_lexer_consume_token(parser->lexer, 1);
3932
3933
12.2k
    njs_parser_next(parser, njs_parser_shift_expression);
3934
3935
12.2k
    return njs_parser_after(parser, current, node, 1,
3936
12.2k
                            njs_parser_relational_expression_match);
3937
12.2k
}
3938
3939
3940
/*
3941
 * 12.11 Equality Operators.
3942
 */
3943
static njs_int_t
3944
njs_parser_equality_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3945
    njs_queue_link_t *current)
3946
2.53M
{
3947
2.53M
    njs_parser_next(parser, njs_parser_relational_expression);
3948
3949
2.53M
    return njs_parser_after(parser, current, NULL, 1,
3950
2.53M
                            njs_parser_equality_expression_match);
3951
2.53M
}
3952
3953
3954
static njs_int_t
3955
njs_parser_equality_expression_match(njs_parser_t *parser,
3956
    njs_lexer_token_t *token, njs_queue_link_t *current)
3957
2.40M
{
3958
2.40M
    njs_parser_node_t       *node;
3959
2.40M
    njs_vmcode_operation_t  operation;
3960
3961
2.40M
    if (parser->target != NULL) {
3962
4.05k
        parser->target->right = parser->node;
3963
4.05k
        parser->target->right->dest = parser->target;
3964
4.05k
        parser->node = parser->target;
3965
4.05k
    }
3966
3967
2.40M
    switch (token->type) {
3968
2.28k
    case NJS_TOKEN_EQUAL:
3969
2.28k
        operation = NJS_VMCODE_EQUAL;
3970
2.28k
        break;
3971
3972
10
    case NJS_TOKEN_NOT_EQUAL:
3973
10
        operation = NJS_VMCODE_NOT_EQUAL;
3974
10
        break;
3975
3976
78
    case NJS_TOKEN_STRICT_EQUAL:
3977
78
        operation = NJS_VMCODE_STRICT_EQUAL;
3978
78
        break;
3979
3980
1.68k
    case NJS_TOKEN_STRICT_NOT_EQUAL:
3981
1.68k
        operation = NJS_VMCODE_STRICT_NOT_EQUAL;
3982
1.68k
        break;
3983
3984
2.39M
    default:
3985
2.39M
        return njs_parser_stack_pop(parser);
3986
2.40M
    }
3987
3988
4.05k
    node = njs_parser_node_new(parser, token->type);
3989
4.05k
    if (node == NULL) {
3990
0
        return NJS_ERROR;
3991
0
    }
3992
3993
4.05k
    node->token_line = token->line;
3994
4.05k
    node->u.operation = operation;
3995
4.05k
    node->left = parser->node;
3996
4.05k
    node->left->dest = node;
3997
3998
4.05k
    njs_lexer_consume_token(parser->lexer, 1);
3999
4000
4.05k
    njs_parser_next(parser, njs_parser_relational_expression);
4001
4002
4.05k
    return njs_parser_after(parser, current, node, 1,
4003
4.05k
                            njs_parser_equality_expression_match);
4004
4.05k
}
4005
4006
4007
/*
4008
 * 12.12 Binary Bitwise Operators.
4009
 */
4010
static njs_int_t
4011
njs_parser_bitwise_AND_expression(njs_parser_t *parser,
4012
    njs_lexer_token_t *token, njs_queue_link_t *current)
4013
2.52M
{
4014
2.52M
    njs_parser_next(parser, njs_parser_equality_expression);
4015
4016
2.52M
    return njs_parser_after(parser, current, NULL, 1,
4017
2.52M
                            njs_parser_bitwise_AND_expression_and);
4018
2.52M
}
4019
4020
4021
static njs_int_t
4022
njs_parser_bitwise_AND_expression_and(njs_parser_t *parser,
4023
    njs_lexer_token_t *token, njs_queue_link_t *current)
4024
2.39M
{
4025
2.39M
    njs_parser_next(parser, njs_parser_equality_expression);
4026
4027
2.39M
    return njs_parser_expression_node(parser, token, current,
4028
2.39M
                                       NJS_TOKEN_BITWISE_AND,
4029
2.39M
                                       NJS_VMCODE_BITWISE_AND,
4030
2.39M
                                       njs_parser_bitwise_AND_expression_and);
4031
2.39M
}
4032
4033
4034
static njs_int_t
4035
njs_parser_bitwise_XOR_expression(njs_parser_t *parser,
4036
    njs_lexer_token_t *token, njs_queue_link_t *current)
4037
2.52M
{
4038
2.52M
    njs_parser_next(parser, njs_parser_bitwise_AND_expression);
4039
4040
2.52M
    return njs_parser_after(parser, current, NULL, 1,
4041
2.52M
                            njs_parser_bitwise_XOR_expression_xor);
4042
2.52M
}
4043
4044
4045
static njs_int_t
4046
njs_parser_bitwise_XOR_expression_xor(njs_parser_t *parser,
4047
    njs_lexer_token_t *token, njs_queue_link_t *current)
4048
2.38M
{
4049
2.38M
    njs_parser_next(parser, njs_parser_bitwise_AND_expression);
4050
4051
2.38M
    return njs_parser_expression_node(parser, token, current,
4052
2.38M
                                       NJS_TOKEN_BITWISE_XOR,
4053
2.38M
                                       NJS_VMCODE_BITWISE_XOR,
4054
2.38M
                                       njs_parser_bitwise_XOR_expression_xor);
4055
2.38M
}
4056
4057
4058
static njs_int_t
4059
njs_parser_bitwise_OR_expression(njs_parser_t *parser,
4060
    njs_lexer_token_t *token, njs_queue_link_t *current)
4061
2.50M
{
4062
2.50M
    njs_parser_next(parser, njs_parser_bitwise_XOR_expression);
4063
4064
2.50M
    return njs_parser_after(parser, current, NULL, 1,
4065
2.50M
                            njs_parser_bitwise_OR_expression_or);
4066
2.50M
}
4067
4068
4069
static njs_int_t
4070
njs_parser_bitwise_OR_expression_or(njs_parser_t *parser,
4071
    njs_lexer_token_t *token, njs_queue_link_t *current)
4072
2.38M
{
4073
2.38M
    njs_parser_next(parser, njs_parser_bitwise_XOR_expression);
4074
4075
2.38M
    return njs_parser_expression_node(parser, token, current,
4076
2.38M
                                       NJS_TOKEN_BITWISE_OR,
4077
2.38M
                                       NJS_VMCODE_BITWISE_OR,
4078
2.38M
                                       njs_parser_bitwise_OR_expression_or);
4079
2.38M
}
4080
4081
4082
/*
4083
 * 12.13 Binary Logical Operators.
4084
 */
4085
static njs_int_t
4086
njs_parser_logical_AND_expression(njs_parser_t *parser,
4087
    njs_lexer_token_t *token, njs_queue_link_t *current)
4088
2.49M
{
4089
2.49M
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4090
4091
2.49M
    return njs_parser_after(parser, current, NULL, 1,
4092
2.49M
                            njs_parser_logical_AND_expression_and);
4093
2.49M
}
4094
4095
4096
static njs_int_t
4097
njs_parser_logical_AND_expression_and(njs_parser_t *parser,
4098
    njs_lexer_token_t *token, njs_queue_link_t *current)
4099
2.35M
{
4100
2.35M
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4101
4102
2.35M
    return njs_parser_expression_node(parser, token, current,
4103
2.35M
                                       NJS_TOKEN_LOGICAL_AND,
4104
2.35M
                                       NJS_VMCODE_TEST_IF_FALSE,
4105
2.35M
                                       njs_parser_logical_AND_expression_and);
4106
2.35M
}
4107
4108
4109
static njs_int_t
4110
njs_parser_logical_OR_expression(njs_parser_t *parser,
4111
    njs_lexer_token_t *token, njs_queue_link_t *current)
4112
2.49M
{
4113
2.49M
    njs_parser_next(parser, njs_parser_logical_AND_expression);
4114
4115
2.49M
    return njs_parser_after(parser, current, NULL, 1,
4116
2.49M
                            njs_parser_logical_OR_expression_or);
4117
2.49M
}
4118
4119
4120
static njs_int_t
4121
njs_parser_logical_OR_expression_or(njs_parser_t *parser,
4122
    njs_lexer_token_t *token, njs_queue_link_t *current)
4123
2.35M
{
4124
2.35M
    njs_parser_next(parser, njs_parser_logical_AND_expression);
4125
4126
2.35M
    return njs_parser_expression_node(parser, token, current,
4127
2.35M
                                       NJS_TOKEN_LOGICAL_OR,
4128
2.35M
                                       NJS_VMCODE_TEST_IF_TRUE,
4129
2.35M
                                       njs_parser_logical_OR_expression_or);
4130
2.35M
}
4131
4132
4133
static njs_int_t
4134
njs_parser_coalesce_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4135
    njs_queue_link_t *current)
4136
2.36M
{
4137
2.36M
    njs_token_type_t   type;
4138
2.36M
    njs_parser_node_t  *node;
4139
4140
2.36M
    node = parser->node;
4141
4142
2.36M
    if (parser->target != NULL) {
4143
5.59k
        parser->target->right = node;
4144
5.59k
        parser->target->right->dest = parser->target;
4145
5.59k
        parser->node = parser->target;
4146
5.59k
    }
4147
4148
2.36M
    if (token->type != NJS_TOKEN_COALESCE) {
4149
2.35M
        return njs_parser_stack_pop(parser);
4150
2.35M
    }
4151
4152
5.59k
    type = node->token_type;
4153
4154
5.59k
    if (parser->lexer->prev_type != NJS_TOKEN_CLOSE_PARENTHESIS
4155
5.59k
        && (type == NJS_TOKEN_LOGICAL_OR || type == NJS_TOKEN_LOGICAL_AND))
4156
0
    {
4157
0
        return njs_parser_failed(parser);
4158
0
    }
4159
4160
5.59k
    node = njs_parser_node_new(parser, NJS_TOKEN_COALESCE);
4161
5.59k
    if (node == NULL) {
4162
0
        return NJS_ERROR;
4163
0
    }
4164
4165
5.59k
    node->token_line = token->line;
4166
5.59k
    node->u.operation = NJS_VMCODE_COALESCE;
4167
5.59k
    node->left = parser->node;
4168
5.59k
    node->left->dest = node;
4169
4170
5.59k
    njs_lexer_consume_token(parser->lexer, 1);
4171
5.59k
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4172
4173
5.59k
    return njs_parser_after(parser, current, node, 1,
4174
5.59k
                            njs_parser_coalesce_expression);
4175
5.59k
}
4176
4177
4178
static njs_int_t
4179
njs_parser_short_circuit_expression(njs_parser_t *parser,
4180
    njs_lexer_token_t *token, njs_queue_link_t *current)
4181
2.49M
{
4182
2.49M
    njs_parser_next(parser, njs_parser_logical_OR_expression);
4183
4184
2.49M
    return njs_parser_after(parser, current, NULL, 1,
4185
2.49M
                            njs_parser_coalesce_expression);
4186
2.49M
}
4187
4188
4189
/*
4190
 * 12.14 Conditional Operator ( ? : ).
4191
 */
4192
static njs_int_t
4193
njs_parser_conditional_expression(njs_parser_t *parser,
4194
    njs_lexer_token_t *token, njs_queue_link_t *current)
4195
2.49M
{
4196
2.49M
    njs_parser_next(parser, njs_parser_short_circuit_expression);
4197
4198
2.49M
    return njs_parser_after(parser, current, NULL, 1,
4199
2.49M
                            njs_parser_conditional_question_mark);
4200
2.49M
}
4201
4202
4203
static njs_int_t
4204
njs_parser_conditional_question_mark(njs_parser_t *parser,
4205
    njs_lexer_token_t *token, njs_queue_link_t *current)
4206
2.35M
{
4207
2.35M
    njs_parser_node_t  *node, *cond;
4208
4209
2.35M
    if (token->type != NJS_TOKEN_CONDITIONAL) {
4210
2.34M
        return njs_parser_stack_pop(parser);
4211
2.34M
    }
4212
4213
10.5k
    cond = njs_parser_node_new(parser, NJS_TOKEN_CONDITIONAL);
4214
10.5k
    if (cond == NULL) {
4215
0
        return NJS_ERROR;
4216
0
    }
4217
4218
10.5k
    cond->token_line = token->line;
4219
10.5k
    cond->left = parser->node;
4220
4221
10.5k
    node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING);
4222
10.5k
    if (node == NULL) {
4223
0
        return NJS_ERROR;
4224
0
    }
4225
4226
10.5k
    node->token_line = token->line;
4227
10.5k
    cond->right = node;
4228
4229
10.5k
    njs_lexer_consume_token(parser->lexer, 1);
4230
4231
10.5k
    if (njs_lexer_in_stack_push(parser->lexer) != NJS_OK) {
4232
0
        return NJS_ERROR;
4233
0
    }
4234
4235
10.5k
    njs_parser_next(parser, njs_parser_assignment_expression);
4236
4237
10.5k
    return njs_parser_after(parser, current, cond, 1,
4238
10.5k
                            njs_parser_conditional_colon);
4239
10.5k
}
4240
4241
4242
static njs_int_t
4243
njs_parser_conditional_colon(njs_parser_t *parser, njs_lexer_token_t *token,
4244
    njs_queue_link_t *current)
4245
9.57k
{
4246
9.57k
    njs_parser_node_t  *node;
4247
4248
9.57k
    if (token->type != NJS_TOKEN_COLON) {
4249
2
        return njs_parser_failed(parser);
4250
2
    }
4251
4252
9.57k
    njs_lexer_in_stack_pop(parser->lexer);
4253
4254
9.57k
    njs_lexer_consume_token(parser->lexer, 1);
4255
4256
9.57k
    node = parser->target->right;
4257
4258
9.57k
    node->left = parser->node;
4259
9.57k
    node->left->dest = parser->target;
4260
4261
9.57k
    njs_parser_next(parser, njs_parser_assignment_expression);
4262
4263
9.57k
    return njs_parser_after(parser, current, parser->target, 1,
4264
9.57k
                            njs_parser_conditional_colon_after);
4265
9.57k
}
4266
4267
4268
static njs_int_t
4269
njs_parser_conditional_colon_after(njs_parser_t *parser,
4270
    njs_lexer_token_t *token, njs_queue_link_t *current)
4271
9.57k
{
4272
9.57k
    njs_parser_node_t  *node;
4273
4274
9.57k
    node = parser->target->right;
4275
4276
9.57k
    node->right = parser->node;
4277
9.57k
    node->right->dest = parser->target;
4278
4279
9.57k
    parser->node = parser->target;
4280
4281
9.57k
    return njs_parser_stack_pop(parser);
4282
9.57k
}
4283
4284
4285
/*
4286
 * 12.15 Assignment Operators.
4287
 */
4288
static njs_int_t
4289
njs_parser_assignment_expression(njs_parser_t *parser,
4290
    njs_lexer_token_t *token, njs_queue_link_t *current)
4291
2.51M
{
4292
2.51M
    njs_int_t  ret;
4293
4294
2.51M
    if (!parser->use_lhs) {
4295
2.51M
        ret = njs_parser_match_arrow_expression(parser, token);
4296
2.51M
        if (ret == NJS_OK) {
4297
25.5k
            njs_parser_next(parser, njs_parser_arrow_function);
4298
4299
25.5k
            return NJS_OK;
4300
4301
2.49M
        } else if (ret == NJS_ERROR) {
4302
0
            return NJS_ERROR;
4303
0
        }
4304
2.51M
    }
4305
4306
2.49M
    njs_parser_next(parser, njs_parser_conditional_expression);
4307
4308
2.49M
    return njs_parser_after(parser, current, NULL, 1,
4309
2.51M
                            njs_parser_assignment_expression_after);
4310
2.51M
}
4311
4312
4313
/*
4314
 * TODO: this function is a crutch.
4315
 * See NJS_TOKEN_OPEN_PARENTHESIS in njs_parser_primary_expression_test.
4316
 * and look CoverParenthesizedExpressionAndArrowParameterList in spec.
4317
 */
4318
static njs_int_t
4319
njs_parser_match_arrow_expression(njs_parser_t *parser,
4320
    njs_lexer_token_t *token)
4321
2.52M
{
4322
2.52M
    njs_bool_t  rest_parameters;
4323
4324
2.52M
    if (token->type == NJS_TOKEN_ASYNC) {
4325
809
        token = njs_lexer_peek_token(parser->lexer, token, 1);
4326
809
        if (token == NULL) {
4327
0
            return NJS_ERROR;
4328
0
        }
4329
809
    }
4330
4331
2.52M
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS
4332
2.52M
        && !njs_lexer_token_is_binding_identifier(token))
4333
1.72M
    {
4334
1.72M
        return NJS_DECLINED;
4335
1.72M
    }
4336
4337
796k
    if (njs_lexer_token_is_binding_identifier(token)) {
4338
727k
        goto arrow;
4339
727k
    }
4340
4341
68.6k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
4342
68.6k
    if (token == NULL) {
4343
0
        return NJS_ERROR;
4344
0
    }
4345
4346
68.6k
    rest_parameters = 0;
4347
4348
70.6k
    while (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
4349
4350
69.8k
        if (rest_parameters) {
4351
0
            return NJS_DECLINED;
4352
0
        }
4353
4354
69.8k
        if (token->type == NJS_TOKEN_ELLIPSIS) {
4355
0
            rest_parameters = 1;
4356
4357
0
            token = njs_lexer_peek_token(parser->lexer, token, 0);
4358
0
            if (token == NULL) {
4359
0
                return NJS_ERROR;
4360
0
            }
4361
0
        }
4362
4363
69.8k
        if (!njs_lexer_token_is_binding_identifier(token)) {
4364
67.7k
            return NJS_DECLINED;
4365
67.7k
        }
4366
4367
2.08k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
4368
2.08k
        if (token == NULL) {
4369
0
            return NJS_ERROR;
4370
0
        }
4371
4372
2.08k
        if (token->type == NJS_TOKEN_COMMA) {
4373
134
            token = njs_lexer_peek_token(parser->lexer, token, 0);
4374
134
            if (token == NULL) {
4375
0
               return NJS_ERROR;
4376
0
            }
4377
134
        }
4378
2.08k
    }
4379
4380
728k
arrow:
4381
4382
728k
    token = njs_lexer_peek_token(parser->lexer, token, 1);
4383
728k
    if (token == NULL) {
4384
0
        return NJS_ERROR;
4385
0
    }
4386
4387
728k
    if (token->type == NJS_TOKEN_LINE_END) {
4388
313k
        return NJS_DECLINED;
4389
313k
    }
4390
4391
414k
    if (token->type != NJS_TOKEN_ARROW) {
4392
389k
        return NJS_DECLINED;
4393
389k
    }
4394
4395
25.5k
    return NJS_OK;
4396
414k
}
4397
4398
4399
static njs_int_t
4400
njs_parser_assignment_expression_after(njs_parser_t *parser,
4401
    njs_lexer_token_t *token, njs_queue_link_t *current)
4402
2.35M
{
4403
2.35M
    return njs_parser_assignment_operator(parser, token, current);
4404
2.35M
}
4405
4406
4407
static njs_int_t
4408
njs_parser_assignment_operator(njs_parser_t *parser, njs_lexer_token_t *token,
4409
    njs_queue_link_t *current)
4410
2.35M
{
4411
2.35M
    njs_token_type_t        type;
4412
2.35M
    njs_parser_node_t       *node;
4413
2.35M
    njs_vmcode_operation_t  operation;
4414
4415
2.35M
    switch (token->type) {
4416
101k
    case NJS_TOKEN_ASSIGNMENT:
4417
101k
        njs_thread_log_debug("JS: =");
4418
101k
        operation = NJS_VMCODE_MOVE;
4419
101k
        break;
4420
4421
3.92k
    case NJS_TOKEN_MULTIPLICATION_ASSIGNMENT:
4422
3.92k
        njs_thread_log_debug("JS: *=");
4423
3.92k
        operation = NJS_VMCODE_MULTIPLICATION;
4424
3.92k
        break;
4425
4426
5.62k
    case NJS_TOKEN_DIVISION_ASSIGNMENT:
4427
5.62k
        njs_thread_log_debug("JS: /=");
4428
5.62k
        operation = NJS_VMCODE_DIVISION;
4429
5.62k
        break;
4430
4431
3.91k
    case NJS_TOKEN_REMAINDER_ASSIGNMENT:
4432
3.91k
        njs_thread_log_debug("JS: %=");
4433
3.91k
        operation = NJS_VMCODE_REMAINDER;
4434
3.91k
        break;
4435
4436
7.26k
    case NJS_TOKEN_ADDITION_ASSIGNMENT:
4437
7.26k
        njs_thread_log_debug("JS: +=");
4438
7.26k
        operation = NJS_VMCODE_ADDITION;
4439
7.26k
        break;
4440
4441
6.28k
    case NJS_TOKEN_SUBTRACTION_ASSIGNMENT:
4442
6.28k
        njs_thread_log_debug("JS: -=");
4443
6.28k
        operation = NJS_VMCODE_SUBTRACTION;
4444
6.28k
        break;
4445
4446
0
    case NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT:
4447
0
        njs_thread_log_debug("JS: <<=");
4448
0
        operation = NJS_VMCODE_LEFT_SHIFT;
4449
0
        break;
4450
4451
0
    case NJS_TOKEN_RIGHT_SHIFT_ASSIGNMENT:
4452
0
        njs_thread_log_debug("JS: >>=");
4453
0
        operation = NJS_VMCODE_RIGHT_SHIFT;
4454
0
        break;
4455
4456
0
    case NJS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
4457
0
        njs_thread_log_debug("JS: >>>=");
4458
0
        operation = NJS_VMCODE_UNSIGNED_RIGHT_SHIFT;
4459
0
        break;
4460
4461
4.99k
    case NJS_TOKEN_BITWISE_AND_ASSIGNMENT:
4462
4.99k
        njs_thread_log_debug("JS: &=");
4463
4.99k
        operation = NJS_VMCODE_BITWISE_AND;
4464
4.99k
        break;
4465
4466
297
    case NJS_TOKEN_BITWISE_XOR_ASSIGNMENT:
4467
297
        njs_thread_log_debug("JS: ^=");
4468
297
        operation = NJS_VMCODE_BITWISE_XOR;
4469
297
        break;
4470
4471
14.7k
    case NJS_TOKEN_BITWISE_OR_ASSIGNMENT:
4472
14.7k
        njs_thread_log_debug("JS: |=");
4473
14.7k
        operation = NJS_VMCODE_BITWISE_OR;
4474
14.7k
        break;
4475
4476
6
    case NJS_TOKEN_EXPONENTIATION_ASSIGNMENT:
4477
6
        njs_thread_log_debug("JS: **=");
4478
6
        operation = NJS_VMCODE_EXPONENTIATION;
4479
6
        break;
4480
4481
2.20M
    default:
4482
2.20M
        return njs_parser_stack_pop(parser);
4483
2.35M
    }
4484
4485
148k
    if (!njs_parser_is_lvalue(parser->node)) {
4486
217
        type = parser->node->token_type;
4487
4488
217
        if (njs_parser_restricted_identifier(type)) {
4489
1
            njs_parser_syntax_error(parser, "Identifier \"%s\" "
4490
1
                                    "is forbidden as left-hand in assignment",
4491
1
                                    (type == NJS_TOKEN_EVAL) ? "eval"
4492
1
                                                             : "arguments");
4493
4494
216
        } else {
4495
216
            njs_parser_ref_error(parser,
4496
216
                                 "Invalid left-hand side in assignment");
4497
216
        }
4498
4499
217
        return NJS_DONE;
4500
217
    }
4501
4502
148k
    node = njs_parser_node_new(parser, token->type);
4503
148k
    if (node == NULL) {
4504
0
        return NJS_ERROR;
4505
0
    }
4506
4507
148k
    node->token_line = token->line;
4508
148k
    node->u.operation = operation;
4509
148k
    node->left = parser->node;
4510
4511
148k
    njs_lexer_consume_token(parser->lexer, 1);
4512
148k
    njs_parser_next(parser, njs_parser_assignment_expression);
4513
4514
148k
    return njs_parser_after(parser, current, node, 1,
4515
148k
                            njs_parser_assignment_operator_after);
4516
148k
}
4517
4518
4519
static njs_int_t
4520
njs_parser_assignment_operator_after(njs_parser_t *parser,
4521
    njs_lexer_token_t *token, njs_queue_link_t *current)
4522
147k
{
4523
147k
    parser->target->right = parser->node;
4524
147k
    parser->node = parser->target;
4525
4526
147k
    return njs_parser_stack_pop(parser);
4527
147k
}
4528
4529
4530
/*
4531
 * 12.16 Comma Operator ( , ).
4532
 */
4533
static njs_int_t
4534
njs_parser_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4535
    njs_queue_link_t *current)
4536
670k
{
4537
670k
    njs_parser_next(parser, njs_parser_assignment_expression);
4538
4539
670k
    return njs_parser_after(parser, current, NULL, 1,
4540
670k
                            njs_parser_expression_comma);
4541
670k
}
4542
4543
4544
static njs_int_t
4545
njs_parser_expression_comma(njs_parser_t *parser, njs_lexer_token_t *token,
4546
    njs_queue_link_t *current)
4547
561k
{
4548
561k
    njs_parser_next(parser, njs_parser_assignment_expression);
4549
4550
561k
    return njs_parser_expression_node(parser, token, current, NJS_TOKEN_COMMA,
4551
561k
                                       0,
4552
561k
                                       njs_parser_expression_comma);
4553
561k
}
4554
4555
4556
/*
4557
 * 13 Statements and Declarations.
4558
 */
4559
static njs_int_t
4560
njs_parser_statement(njs_parser_t *parser, njs_lexer_token_t *token,
4561
    njs_queue_link_t *current)
4562
662k
{
4563
662k
    njs_int_t                 ret;
4564
662k
    njs_queue_link_t          *lnk;
4565
662k
    njs_parser_stack_entry_t  *entry;
4566
4567
662k
    if (token->type == NJS_TOKEN_END) {
4568
4.31k
        lnk = njs_queue_next(njs_queue_first(&parser->stack));
4569
4570
4.31k
        if (lnk == njs_queue_head(&parser->stack)) {
4571
0
            return njs_parser_reject(parser);
4572
0
        }
4573
4574
4.31k
        entry = njs_queue_link_data(lnk, njs_parser_stack_entry_t, link);
4575
4576
4.31k
        if (entry->state == njs_parser_check_error_state) {
4577
4.30k
            return NJS_DONE;
4578
4.30k
        }
4579
4580
12
        return njs_parser_reject(parser);
4581
4.31k
    }
4582
4583
658k
    switch (token->type) {
4584
18.8k
    case NJS_TOKEN_SEMICOLON:
4585
18.8k
        njs_lexer_consume_token(parser->lexer, 1);
4586
18.8k
        return njs_parser_stack_pop(parser);
4587
4588
0
    case NJS_TOKEN_EXPORT:
4589
0
        parser->line = token->line;
4590
4591
0
        njs_lexer_consume_token(parser->lexer, 1);
4592
0
        njs_parser_next(parser, njs_parser_export);
4593
4594
0
        return njs_parser_after(parser, current, parser->node, 1,
4595
0
                                njs_parser_statement_after);
4596
4597
0
    case NJS_TOKEN_IMPORT:
4598
0
        parser->line = token->line;
4599
4600
0
        njs_lexer_consume_token(parser->lexer, 1);
4601
0
        njs_parser_next(parser, njs_parser_import);
4602
4603
0
        return njs_parser_after(parser, current, parser->node, 1,
4604
0
                                njs_parser_statement_after);
4605
639k
    default:
4606
639k
        break;
4607
658k
    }
4608
4609
639k
    ret = njs_parser_statement_wo_node(parser, token, current);
4610
639k
    if (ret != NJS_OK) {
4611
0
        return ret;
4612
0
    }
4613
4614
639k
    return njs_parser_after(parser, current, parser->node, 1,
4615
639k
                            njs_parser_statement_after);
4616
639k
}
4617
4618
4619
static njs_int_t
4620
njs_parser_statement_wo_node(njs_parser_t *parser, njs_lexer_token_t *token,
4621
    njs_queue_link_t *current)
4622
664k
{
4623
664k
    switch (token->type) {
4624
41.9k
    case NJS_TOKEN_OPEN_BRACE:
4625
41.9k
        njs_parser_next(parser, njs_parser_block_statement);
4626
41.9k
        break;
4627
4628
4.83k
    case NJS_TOKEN_VAR:
4629
4.83k
        njs_lexer_consume_token(parser->lexer, 1);
4630
4.83k
        return njs_parser_variable_statement(parser, token, current);
4631
4632
514
    case NJS_TOKEN_SEMICOLON:
4633
514
        njs_lexer_consume_token(parser->lexer, 1);
4634
514
        return njs_parser_stack_pop(parser);
4635
4636
2.05k
    case NJS_TOKEN_IF:
4637
2.05k
        njs_parser_next(parser, njs_parser_if_statement);
4638
2.05k
        break;
4639
4640
    /* BreakableStatement */
4641
292
    case NJS_TOKEN_DO:
4642
292
        njs_parser_next(parser, njs_parser_iteration_statement_do);
4643
292
        break;
4644
4645
1
    case NJS_TOKEN_WHILE:
4646
1
        njs_parser_next(parser, njs_parser_iteration_statement_while);
4647
1
        break;
4648
4649
7.92k
    case NJS_TOKEN_FOR:
4650
7.92k
        njs_parser_next(parser, njs_parser_iteration_statement_for);
4651
7.92k
        break;
4652
4653
648
    case NJS_TOKEN_SWITCH:
4654
648
        njs_parser_next(parser, njs_parser_switch_statement);
4655
648
        break;
4656
4657
144
    case NJS_TOKEN_CONTINUE:
4658
144
        njs_parser_next(parser, njs_parser_continue_statement);
4659
144
        break;
4660
4661
8.70k
    case NJS_TOKEN_BREAK:
4662
8.70k
        njs_parser_next(parser, njs_parser_break_statement);
4663
8.70k
        break;
4664
4665
1.93k
    case NJS_TOKEN_RETURN:
4666
1.93k
        njs_parser_next(parser, njs_parser_return_statement);
4667
1.93k
        break;
4668
4669
2.82k
    case NJS_TOKEN_WITH:
4670
2.82k
        njs_parser_next(parser, njs_parser_with_statement);
4671
2.82k
        break;
4672
4673
1.14k
    case NJS_TOKEN_THROW:
4674
1.14k
        njs_parser_next(parser, njs_parser_throw_statement);
4675
1.14k
        break;
4676
4677
3.30k
    case NJS_TOKEN_TRY:
4678
3.30k
        njs_parser_next(parser, njs_parser_try_statement);
4679
3.30k
        break;
4680
4681
54.9k
    case NJS_TOKEN_DEBUGGER:
4682
54.9k
        njs_parser_next(parser, njs_parser_debugger_statement);
4683
54.9k
        break;
4684
4685
0
    case NJS_TOKEN_END:
4686
0
        return njs_parser_failed(parser);
4687
4688
533k
    default:
4689
533k
        if (njs_lexer_token_is_identifier_reference(token)) {
4690
456k
            token = njs_lexer_peek_token(parser->lexer, token, 0);
4691
456k
            if (token == NULL) {
4692
0
                return NJS_ERROR;
4693
0
            }
4694
4695
456k
            if (token->type == NJS_TOKEN_COLON) {
4696
15.9k
                njs_parser_next(parser, njs_parser_labelled_statement);
4697
15.9k
                return NJS_OK;
4698
15.9k
            }
4699
456k
        }
4700
4701
517k
        njs_parser_next(parser, njs_parser_expression_statement);
4702
517k
        return NJS_OK;
4703
664k
    }
4704
4705
125k
    parser->line = token->line;
4706
4707
125k
    njs_lexer_consume_token(parser->lexer, 1);
4708
4709
125k
    return NJS_OK;
4710
664k
}
4711
4712
4713
static njs_int_t
4714
njs_parser_statement_after(njs_parser_t *parser, njs_lexer_token_t *token,
4715
    njs_queue_link_t *current)
4716
540k
{
4717
540k
    njs_parser_node_t  *stmt, *last, *new_node, **child;
4718
540k
    njs_parser_node_t  *node, *top;
4719
4720
540k
    child = &parser->target;
4721
540k
    last = *child;
4722
4723
540k
    new_node = parser->node;
4724
4725
540k
    if (new_node != NULL) {
4726
540k
        if (new_node->hoist) {
4727
0
            child = &njs_parser_chain_top(parser);
4728
4729
0
            while (*child != NULL) {
4730
0
                node = *child;
4731
4732
0
                if (node->hoist) {
4733
0
                    break;
4734
0
                }
4735
4736
0
                child = &node->left;
4737
0
            }
4738
4739
0
            last = *child;
4740
0
        }
4741
4742
540k
        stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
4743
540k
        if (njs_slow_path(stmt == NULL)) {
4744
0
            return NJS_ERROR;
4745
0
        }
4746
4747
540k
        stmt->hoist = new_node->hoist;
4748
540k
        stmt->left = last;
4749
540k
        stmt->right = new_node;
4750
4751
540k
        *child = stmt;
4752
4753
540k
        top = (child != &parser->target) ? njs_parser_chain_top(parser)
4754
540k
                                         : stmt;
4755
4756
540k
        parser->node = top;
4757
4758
540k
       njs_parser_chain_top_set(parser, top);
4759
540k
    }
4760
4761
540k
    return njs_parser_stack_pop(parser);
4762
540k
}
4763
4764
4765
static njs_int_t
4766
njs_parser_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
4767
    njs_queue_link_t *current)
4768
675k
{
4769
675k
    njs_int_t  ret;
4770
4771
675k
    ret = njs_parser_hoistable_declaration(parser, token, current);
4772
675k
    if (ret == NJS_OK) {
4773
1.57k
        return NJS_OK;
4774
1.57k
    }
4775
4776
673k
    switch (token->type) {
4777
0
    case NJS_TOKEN_CLASS:
4778
0
        njs_parser_next(parser, njs_parser_class_declaration);
4779
0
        return NJS_OK;
4780
4781
2.91k
    case NJS_TOKEN_LET:
4782
15.2k
    case NJS_TOKEN_CONST:
4783
15.2k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
4784
15.2k
        if (token == NULL) {
4785
0
            return NJS_ERROR;
4786
0
        }
4787
4788
15.2k
        switch (token->type) {
4789
0
        case NJS_TOKEN_OPEN_BRACE:
4790
0
        case NJS_TOKEN_OPEN_BRACKET:
4791
0
            njs_parser_next(parser, njs_parser_lexical_declaration);
4792
0
            break;
4793
4794
15.2k
        default:
4795
15.2k
            if (njs_lexer_token_is_reserved(token)) {
4796
0
                njs_lexer_consume_token(parser->lexer, 1);
4797
0
                njs_parser_next(parser, njs_parser_failed_state);
4798
0
                return NJS_OK;
4799
0
            }
4800
4801
15.2k
            if (njs_lexer_token_is_binding_identifier(token)) {
4802
11.1k
                njs_parser_next(parser, njs_parser_lexical_declaration);
4803
11.1k
                break;
4804
11.1k
            }
4805
4806
4.10k
            return NJS_DECLINED;
4807
15.2k
        }
4808
4809
11.1k
        break;
4810
4811
658k
    default:
4812
658k
        return NJS_DECLINED;
4813
673k
    }
4814
4815
11.1k
    return njs_parser_after(parser, current, parser->node, 1,
4816
673k
                            njs_parser_statement_after);
4817
673k
}
4818
4819
4820
static njs_int_t
4821
njs_parser_hoistable_declaration(njs_parser_t *parser,
4822
    njs_lexer_token_t *token, njs_queue_link_t *current)
4823
675k
{
4824
675k
    njs_int_t  ret;
4825
4826
675k
    ret = njs_parser_function_or_generator(parser, token, current);
4827
675k
    if (ret == NJS_OK) {
4828
1.56k
        return NJS_OK;
4829
1.56k
    }
4830
4831
673k
    ret = njs_parser_async_function_or_generator(parser, token, current);
4832
673k
    if (ret == NJS_OK) {
4833
7
        return NJS_OK;
4834
7
    }
4835
4836
673k
    return NJS_DECLINED;
4837
673k
}
4838
4839
4840
/*
4841
 * 13.2 Block.
4842
 */
4843
static njs_int_t
4844
njs_parser_block_statement(njs_parser_t *parser, njs_lexer_token_t *token,
4845
    njs_queue_link_t *current)
4846
46.2k
{
4847
46.2k
    void       *target;
4848
46.2k
    njs_int_t  ret;
4849
4850
46.2k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK, 0);
4851
46.2k
    if (ret != NJS_OK) {
4852
0
        return NJS_ERROR;
4853
0
    }
4854
4855
46.2k
    target = (void *) (uintptr_t) parser->line;
4856
46.2k
    parser->node = NULL;
4857
4858
46.2k
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
4859
6.18k
        parser->target = target;
4860
4861
6.18k
        njs_parser_next(parser, njs_parser_block_statement_close_brace);
4862
6.18k
        return NJS_OK;
4863
6.18k
    }
4864
4865
40.0k
    njs_parser_next(parser, njs_parser_statement_list);
4866
4867
40.0k
    return njs_parser_after(parser, current, target, 0,
4868
46.2k
                            njs_parser_block_statement_close_brace);
4869
46.2k
}
4870
4871
4872
static njs_int_t
4873
njs_parser_block_statement_open_brace(njs_parser_t *parser,
4874
    njs_lexer_token_t *token, njs_queue_link_t *current)
4875
4.28k
{
4876
4.28k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
4877
0
        return njs_parser_failed(parser);
4878
0
    }
4879
4880
4.28k
    parser->line = token->line;
4881
4882
4.28k
    njs_lexer_consume_token(parser->lexer, 1);
4883
4884
4.28k
    token = njs_lexer_token(parser->lexer, 0);
4885
4.28k
    if (token == NULL) {
4886
0
        return NJS_ERROR;
4887
0
    }
4888
4889
4.28k
    return njs_parser_block_statement(parser, token, current);
4890
4.28k
}
4891
4892
4893
static njs_int_t
4894
njs_parser_block_statement_close_brace(njs_parser_t *parser,
4895
    njs_lexer_token_t *token, njs_queue_link_t *current)
4896
15.0k
{
4897
15.0k
    njs_parser_node_t  *node;
4898
4899
15.0k
    if (parser->ret != NJS_OK) {
4900
11
        return njs_parser_failed(parser);
4901
11
    }
4902
4903
15.0k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
4904
0
        return njs_parser_failed(parser);
4905
0
    }
4906
4907
15.0k
    node = njs_parser_node_new(parser, NJS_TOKEN_BLOCK);
4908
15.0k
    if (node == NULL) {
4909
0
        return NJS_ERROR;
4910
0
    }
4911
4912
15.0k
    node->token_line = (uint32_t) (uintptr_t) parser->target;
4913
15.0k
    node->left = parser->node;
4914
15.0k
    node->right = NULL;
4915
4916
15.0k
    parser->target = NULL;
4917
15.0k
    parser->node = node;
4918
4919
15.0k
    njs_parser_scope_end(parser);
4920
4921
15.0k
    njs_lexer_consume_token(parser->lexer, 1);
4922
15.0k
    return njs_parser_stack_pop(parser);
4923
15.0k
}
4924
4925
4926
static njs_int_t
4927
njs_parser_statement_list(njs_parser_t *parser, njs_lexer_token_t *token,
4928
    njs_queue_link_t *current)
4929
147k
{
4930
147k
    njs_parser_next(parser, njs_parser_statement_list_item);
4931
4932
147k
    return njs_parser_after(parser, current, NULL, 1,
4933
147k
                            njs_parser_statement_list_next);
4934
147k
}
4935
4936
4937
static njs_int_t
4938
njs_parser_statement_list_next(njs_parser_t *parser, njs_lexer_token_t *token,
4939
    njs_queue_link_t *current)
4940
565k
{
4941
565k
    if (parser->ret != NJS_OK) {
4942
6.99k
        if (token->type != NJS_TOKEN_CLOSE_BRACE) {
4943
6.99k
            parser->node = parser->target;
4944
4945
6.99k
            (void) njs_parser_stack_pop(parser);
4946
4947
6.99k
            return parser->ret;
4948
6.99k
        }
4949
4950
0
        return njs_parser_failed(parser);
4951
6.99k
    }
4952
4953
558k
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
4954
31.1k
        return njs_parser_stack_pop(parser);
4955
31.1k
    }
4956
4957
527k
    njs_parser_next(parser, njs_parser_statement_list_item);
4958
4959
527k
    return njs_parser_after(parser, current, parser->node, 0,
4960
558k
                            njs_parser_statement_list_next);
4961
558k
}
4962
4963
4964
static njs_int_t
4965
njs_parser_statement_list_item(njs_parser_t *parser, njs_lexer_token_t *token,
4966
    njs_queue_link_t *current)
4967
675k
{
4968
675k
    njs_int_t  ret;
4969
4970
675k
    ret = njs_parser_declaration(parser, token, current);
4971
675k
    if (ret == NJS_OK) {
4972
12.7k
        return NJS_OK;
4973
12.7k
    }
4974
4975
662k
    njs_parser_next(parser, njs_parser_statement);
4976
4977
662k
    return NJS_OK;
4978
675k
}
4979
4980
4981
/*
4982
 * 13.3.1 Let and Const Declarations
4983
 */
4984
static njs_int_t
4985
njs_parser_lexical_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
4986
    njs_queue_link_t *current)
4987
11.1k
{
4988
11.1k
    parser->var_type = (token->type == NJS_TOKEN_LET) ? NJS_VARIABLE_LET
4989
11.1k
                                                      : NJS_VARIABLE_CONST;
4990
4991
11.1k
    njs_lexer_consume_token(parser->lexer, 1);
4992
4993
11.1k
    njs_parser_next(parser, njs_parser_variable_declaration_list);
4994
4995
11.1k
    return njs_parser_after(parser, current, NULL, 1, njs_parser_semicolon);
4996
11.1k
}
4997
4998
4999
/*
5000
 * 13.3.2 Variable Statement
5001
 */
5002
static njs_int_t
5003
njs_parser_variable_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5004
    njs_queue_link_t *current)
5005
4.83k
{
5006
4.83k
    parser->var_type = NJS_VARIABLE_VAR;
5007
5008
4.83k
    njs_parser_next(parser, njs_parser_variable_declaration_list);
5009
5010
4.83k
    return njs_parser_after(parser, current, NULL, 1, njs_parser_semicolon);
5011
4.83k
}
5012
5013
5014
static njs_int_t
5015
njs_parser_variable_declaration_list(njs_parser_t *parser,
5016
    njs_lexer_token_t *token, njs_queue_link_t *current)
5017
15.9k
{
5018
15.9k
    njs_parser_next(parser, njs_parser_variable_declaration);
5019
5020
15.9k
    return njs_parser_after(parser, current, NULL, 1,
5021
15.9k
                            njs_parser_variable_declaration_list_next);
5022
15.9k
}
5023
5024
5025
static njs_int_t
5026
njs_parser_variable_declaration_list_next(njs_parser_t *parser,
5027
    njs_lexer_token_t *token, njs_queue_link_t *current)
5028
17.5k
{
5029
17.5k
    njs_parser_node_t  *node;
5030
5031
17.5k
    if (parser->target != NULL) {
5032
3.62k
        parser->node->left = parser->target;
5033
3.62k
    }
5034
5035
17.5k
    if (token->type != NJS_TOKEN_COMMA) {
5036
13.9k
        return njs_parser_stack_pop(parser);
5037
13.9k
    }
5038
5039
3.62k
    njs_lexer_consume_token(parser->lexer, 1);
5040
5041
3.62k
    node = parser->node;
5042
5043
3.62k
    parser->node = NULL;
5044
5045
3.62k
    njs_parser_next(parser, njs_parser_variable_declaration);
5046
5047
3.62k
    return njs_parser_after(parser, current, node, 1,
5048
17.5k
                            njs_parser_variable_declaration_list_next);
5049
17.5k
}
5050
5051
5052
static njs_int_t
5053
njs_parser_variable_declaration(njs_parser_t *parser,
5054
    njs_lexer_token_t *token, njs_queue_link_t *current)
5055
19.6k
{
5056
19.6k
    njs_int_t          ret;
5057
19.6k
    njs_variable_t     *var;
5058
19.6k
    njs_token_type_t   type;
5059
19.6k
    njs_parser_node_t  *name;
5060
5061
19.6k
    ret = njs_parser_binding_pattern(parser, token, current);
5062
19.6k
    if (ret == NJS_OK) {
5063
0
        return njs_parser_after(parser, current, NULL, 1,
5064
0
                                njs_parser_initializer);
5065
0
    }
5066
5067
19.6k
    if (!njs_lexer_token_is_binding_identifier(token)) {
5068
0
        return njs_parser_failed(parser);
5069
0
    }
5070
5071
19.6k
    if (njs_parser_restricted_identifier(token->type)) {
5072
0
        njs_parser_syntax_error(parser, "Identifier \"%V\" is forbidden in"
5073
0
                                " var declaration", &token->text);
5074
0
        return NJS_DONE;
5075
0
    }
5076
5077
19.6k
    name = njs_parser_variable_node(parser, token->unique_id, parser->var_type,
5078
19.6k
                                    &var);
5079
19.6k
    if (name == NULL) {
5080
2.05k
        return NJS_ERROR;
5081
2.05k
    }
5082
5083
17.5k
    if (var->self) {
5084
1.72k
        var->type = parser->var_type;
5085
1.72k
        var->self = 0;
5086
1.72k
    }
5087
5088
17.5k
    name->token_line = token->line;
5089
5090
17.5k
    parser->node = name;
5091
5092
17.5k
    njs_lexer_consume_token(parser->lexer, 1);
5093
5094
17.5k
    token = njs_lexer_token(parser->lexer, 0);
5095
17.5k
    if (token == NULL) {
5096
0
        return NJS_ERROR;
5097
0
    }
5098
5099
17.5k
    switch (parser->var_type) {
5100
3.54k
    case NJS_VARIABLE_LET:
5101
3.54k
        type = NJS_TOKEN_LET;
5102
3.54k
        break;
5103
5104
6.17k
    case NJS_VARIABLE_CONST:
5105
6.17k
        type = NJS_TOKEN_CONST;
5106
6.17k
        break;
5107
5108
7.85k
    default:
5109
7.85k
        type = NJS_TOKEN_VAR;
5110
7.85k
        break;
5111
17.5k
    }
5112
5113
17.5k
    ret = njs_parser_initializer_assign(parser, type);
5114
17.5k
    if (ret != NJS_OK) {
5115
0
        return ret;
5116
0
    }
5117
5118
17.5k
    parser->node->token_line = token->line;
5119
5120
17.5k
    if (token->type == NJS_TOKEN_ASSIGNMENT) {
5121
6.23k
        njs_parser_next(parser, njs_parser_initializer);
5122
5123
6.23k
        return NJS_OK;
5124
6.23k
    }
5125
5126
11.3k
    parser->target = parser->node;
5127
11.3k
    parser->node = NULL;
5128
5129
11.3k
    njs_parser_next(parser, njs_parser_initializer_after);
5130
5131
11.3k
    return NJS_OK;
5132
17.5k
}
5133
5134
5135
/*
5136
 * 13.3.3 Destructuring Binding Patterns.
5137
 */
5138
static njs_int_t
5139
njs_parser_binding_pattern(njs_parser_t *parser, njs_lexer_token_t *token,
5140
    njs_queue_link_t *current)
5141
19.6k
{
5142
19.6k
    if (token->type == NJS_TOKEN_OPEN_BRACE) {
5143
0
        njs_parser_next(parser, njs_parser_object_binding_pattern);
5144
5145
19.6k
    } else if (token->type == NJS_TOKEN_OPEN_BRACKET) {
5146
0
        njs_parser_next(parser, njs_parser_array_binding_pattern);
5147
5148
19.6k
    } else {
5149
19.6k
        return NJS_DECLINED;
5150
19.6k
    }
5151
5152
0
    njs_lexer_consume_token(parser->lexer, 1);
5153
5154
0
    return NJS_OK;
5155
19.6k
}
5156
5157
static njs_int_t
5158
njs_parser_object_binding_pattern(njs_parser_t *parser,
5159
    njs_lexer_token_t *token, njs_queue_link_t *current)
5160
0
{
5161
0
    return njs_parser_not_supported(parser, token);
5162
0
}
5163
5164
5165
static njs_int_t
5166
njs_parser_array_binding_pattern(njs_parser_t *parser,
5167
    njs_lexer_token_t *token, njs_queue_link_t *current)
5168
0
{
5169
0
    return njs_parser_not_supported(parser, token);
5170
0
}
5171
5172
5173
/*
5174
 * 13.5 Expression Statement.
5175
 */
5176
static njs_int_t
5177
njs_parser_expression_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5178
    njs_queue_link_t *current)
5179
517k
{
5180
517k
    njs_token_type_t   type;
5181
517k
    njs_lexer_token_t  *next;
5182
5183
517k
    switch (token->type) {
5184
0
    case NJS_TOKEN_FUNCTION:
5185
0
        njs_parser_syntax_error(parser, "Functions can only be declared "
5186
0
                                        "at top level or inside a block");
5187
0
        return NJS_DONE;
5188
5189
0
    case NJS_TOKEN_CLASS:
5190
0
        njs_parser_syntax_error(parser, "Class can only be declared "
5191
0
                                        "at top level or inside a block");
5192
0
        return NJS_DONE;
5193
5194
0
    case NJS_TOKEN_OPEN_BRACE:
5195
0
        return njs_parser_reject(parser);
5196
5197
0
    case NJS_TOKEN_ASYNC:
5198
0
        next = njs_lexer_peek_token(parser->lexer, token, 1);
5199
0
        if (next == NULL) {
5200
0
            return NJS_ERROR;
5201
0
        }
5202
5203
0
        if (next->type == NJS_TOKEN_FUNCTION) {
5204
0
            return njs_parser_not_supported(parser, token);
5205
0
        }
5206
5207
0
        break;
5208
5209
4.10k
    case NJS_TOKEN_CONST:
5210
4.10k
    case NJS_TOKEN_LET:
5211
4.10k
        type = token->type;
5212
5213
4.10k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
5214
4.10k
        if (token == NULL) {
5215
0
            return NJS_ERROR;
5216
0
        }
5217
5218
4.10k
        if (token->type == NJS_TOKEN_NAME) {
5219
0
            njs_parser_syntax_error(parser, "%s declaration cannot appear "
5220
0
                                    "in a single-statement context",
5221
0
                                    (type == NJS_TOKEN_CONST ? "const"
5222
0
                                                             : "let" ));
5223
0
            return NJS_DONE;
5224
0
        }
5225
5226
4.10k
        if (token->type == NJS_TOKEN_OPEN_BRACKET) {
5227
0
            return njs_parser_failed(parser);
5228
0
        }
5229
5230
4.10k
        break;
5231
5232
513k
    default:
5233
513k
        break;
5234
517k
    }
5235
5236
517k
    parser->node = NULL;
5237
5238
517k
    njs_parser_next(parser, njs_parser_expression);
5239
5240
517k
    return njs_parser_after(parser, current, NULL, 1,
5241
517k
                            njs_parser_expression_statement_after);
5242
517k
}
5243
5244
5245
static njs_int_t
5246
njs_parser_expression_statement_after(njs_parser_t *parser,
5247
    njs_lexer_token_t *token, njs_queue_link_t *current)
5248
453k
{
5249
453k
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
5250
3.33k
        return njs_parser_failed(parser);
5251
3.33k
    }
5252
5253
450k
    return njs_parser_stack_pop(parser);
5254
453k
}
5255
5256
5257
/*
5258
 * 13.6 if Statement.
5259
 */
5260
static njs_int_t
5261
njs_parser_if_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5262
    njs_queue_link_t *current)
5263
2.05k
{
5264
2.05k
    njs_int_t          ret;
5265
2.05k
    njs_parser_node_t  *node;
5266
5267
2.05k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
5268
0
        return njs_parser_failed(parser);
5269
0
    }
5270
5271
2.05k
    njs_lexer_consume_token(parser->lexer, 1);
5272
5273
2.05k
    node = njs_parser_node_new(parser, NJS_TOKEN_IF);
5274
2.05k
    if (node == NULL) {
5275
0
        return NJS_ERROR;
5276
0
    }
5277
5278
2.05k
    node->token_line = parser->line;
5279
5280
2.05k
    parser->node = NULL;
5281
5282
2.05k
    njs_parser_next(parser, njs_parser_expression);
5283
5284
2.05k
    ret = njs_parser_after(parser, current, node, 1,
5285
2.05k
                           njs_parser_if_close_parenthesis);
5286
2.05k
    if (ret != NJS_OK) {
5287
0
        return ret;
5288
0
    }
5289
5290
2.05k
    ret = njs_parser_after(parser, current, NULL, 1,
5291
2.05k
                           njs_parser_statement_wo_node);
5292
2.05k
    if (ret != NJS_OK) {
5293
0
        return ret;
5294
0
    }
5295
5296
2.05k
    return njs_parser_after(parser, current, node, 1,
5297
2.05k
                            njs_parser_else_statement);
5298
2.05k
}
5299
5300
5301
static njs_int_t
5302
njs_parser_if_close_parenthesis(njs_parser_t *parser, njs_lexer_token_t *token,
5303
    njs_queue_link_t *current)
5304
2.05k
{
5305
2.05k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
5306
0
        return njs_parser_failed(parser);
5307
0
    }
5308
5309
2.05k
    njs_lexer_consume_token(parser->lexer, 1);
5310
5311
2.05k
    parser->target->left = parser->node;
5312
2.05k
    parser->node = NULL;
5313
5314
2.05k
    return njs_parser_stack_pop(parser);
5315
2.05k
}
5316
5317
5318
static njs_int_t
5319
njs_parser_else_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5320
    njs_queue_link_t *current)
5321
2.05k
{
5322
2.05k
    njs_parser_node_t  *node;
5323
5324
2.05k
    parser->target->right = parser->node;
5325
2.05k
    parser->node = NULL;
5326
5327
2.05k
    if (token->type == NJS_TOKEN_ELSE) {
5328
736
        node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING);
5329
736
        if (node == NULL) {
5330
0
            return NJS_ERROR;
5331
0
        }
5332
5333
736
        node->token_line = token->line;
5334
736
        node->left = parser->target->right;
5335
5336
736
        parser->target->right = node;
5337
5338
736
        njs_lexer_consume_token(parser->lexer, 1);
5339
736
        njs_parser_next(parser, njs_parser_statement_wo_node);
5340
5341
736
        return njs_parser_after(parser, current, parser->target, 1,
5342
736
                                njs_parser_else_statement_after);
5343
736
    }
5344
5345
1.31k
    parser->node = parser->target;
5346
5347
1.31k
    return njs_parser_stack_pop(parser);
5348
2.05k
}
5349
5350
5351
static njs_int_t
5352
njs_parser_else_statement_after(njs_parser_t *parser, njs_lexer_token_t *token,
5353
    njs_queue_link_t *current)
5354
735
{
5355
735
    parser->target->right->right = parser->node;
5356
5357
735
    parser->node = parser->target;
5358
5359
735
    return njs_parser_stack_pop(parser);
5360
735
}
5361
5362
5363
static njs_int_t
5364
njs_parser_iteration_statement_do(njs_parser_t *parser,
5365
    njs_lexer_token_t *token, njs_queue_link_t *current)
5366
292
{
5367
292
    njs_parser_node_t  *node;
5368
5369
292
    node = njs_parser_node_new(parser, NJS_TOKEN_DO);
5370
292
    if (node == NULL) {
5371
0
        return NJS_ERROR;
5372
0
    }
5373
5374
292
    node->token_line = parser->line;
5375
5376
292
    parser->node = NULL;
5377
5378
292
    njs_parser_next(parser, njs_parser_statement_wo_node);
5379
5380
292
    return njs_parser_after(parser, current, node, 1,
5381
292
                            njs_parser_iteration_statement_do_while);
5382
292
}
5383
5384
5385
static njs_int_t
5386
njs_parser_iteration_statement_do_while(njs_parser_t *parser,
5387
    njs_lexer_token_t *token, njs_queue_link_t *current)
5388
291
{
5389
291
    if (token->type != NJS_TOKEN_WHILE) {
5390
2
        return njs_parser_failed(parser);
5391
2
    }
5392
5393
289
    parser->target->left = parser->node;
5394
5395
289
    njs_lexer_consume_token(parser->lexer, 1);
5396
5397
289
    njs_parser_next(parser, njs_parser_expression_parenthesis);
5398
5399
289
    return njs_parser_after(parser, current, parser->target, 1,
5400
291
                            njs_parser_do_while_semicolon);
5401
291
}
5402
5403
5404
static njs_int_t
5405
njs_parser_do_while_semicolon(njs_parser_t *parser, njs_lexer_token_t *token,
5406
    njs_queue_link_t *current)
5407
289
{
5408
289
    if (parser->strict_semicolon) {
5409
0
        return njs_parser_failed(parser);
5410
0
    }
5411
5412
289
    parser->target->right = parser->node;
5413
289
    parser->node = parser->target;
5414
5415
289
    return njs_parser_stack_pop(parser);
5416
289
}
5417
5418
5419
static njs_int_t
5420
njs_parser_iteration_statement_while(njs_parser_t *parser,
5421
    njs_lexer_token_t *token, njs_queue_link_t *current)
5422
1
{
5423
1
    njs_parser_node_t  *node;
5424
5425
1
    node = njs_parser_node_new(parser, NJS_TOKEN_WHILE);
5426
1
    if