1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "js-parser-internal.h"
17425bb815Sopenharmony_ci#include "js-scanner-internal.h"
18425bb815Sopenharmony_ci#include "lit-char-helpers.h"
19425bb815Sopenharmony_ci
20425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER)
21425bb815Sopenharmony_ci
22425bb815Sopenharmony_ci/** \addtogroup parser Parser
23425bb815Sopenharmony_ci * @{
24425bb815Sopenharmony_ci *
25425bb815Sopenharmony_ci * \addtogroup jsparser JavaScript
26425bb815Sopenharmony_ci * @{
27425bb815Sopenharmony_ci *
28425bb815Sopenharmony_ci * \addtogroup jsparser_scanner Scanner
29425bb815Sopenharmony_ci * @{
30425bb815Sopenharmony_ci */
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
33425bb815Sopenharmony_ci
34425bb815Sopenharmony_ci/**
35425bb815Sopenharmony_ci * Add the "async" literal to the literal pool.
36425bb815Sopenharmony_ci */
37425bb815Sopenharmony_civoid
38425bb815Sopenharmony_ciscanner_add_async_literal (parser_context_t *context_p, /**< context */
39425bb815Sopenharmony_ci                           scanner_context_t *scanner_context_p) /**< scanner context */
40425bb815Sopenharmony_ci{
41425bb815Sopenharmony_ci  lexer_lit_location_t async_literal;
42425bb815Sopenharmony_ci
43425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC);
44425bb815Sopenharmony_ci
45425bb815Sopenharmony_ci  parser_stack_pop_uint8 (context_p);
46425bb815Sopenharmony_ci  parser_stack_pop (context_p, &async_literal, sizeof (lexer_lit_location_t));
47425bb815Sopenharmony_ci
48425bb815Sopenharmony_ci  lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
49425bb815Sopenharmony_ci                                                                     scanner_context_p->active_literal_pool_p,
50425bb815Sopenharmony_ci                                                                     &async_literal);
51425bb815Sopenharmony_ci
52425bb815Sopenharmony_ci  lit_location_p->type |= SCANNER_LITERAL_IS_USED;
53425bb815Sopenharmony_ci
54425bb815Sopenharmony_ci  if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
55425bb815Sopenharmony_ci  {
56425bb815Sopenharmony_ci    lit_location_p->type |= SCANNER_LITERAL_NO_REG;
57425bb815Sopenharmony_ci  }
58425bb815Sopenharmony_ci} /* scanner_add_async_literal */
59425bb815Sopenharmony_ci
60425bb815Sopenharmony_ci/**
61425bb815Sopenharmony_ci * Init scanning the body of an arrow function.
62425bb815Sopenharmony_ci */
63425bb815Sopenharmony_cistatic void
64425bb815Sopenharmony_ciscanner_check_arrow_body (parser_context_t *context_p, /**< context */
65425bb815Sopenharmony_ci                          scanner_context_t *scanner_context_p) /**< scanner context */
66425bb815Sopenharmony_ci{
67425bb815Sopenharmony_ci  lexer_next_token (context_p);
68425bb815Sopenharmony_ci
69425bb815Sopenharmony_ci  if (context_p->token.type != LEXER_LEFT_BRACE)
70425bb815Sopenharmony_ci  {
71425bb815Sopenharmony_ci    scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
72425bb815Sopenharmony_ci    parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_EXPRESSION);
73425bb815Sopenharmony_ci    return;
74425bb815Sopenharmony_ci  }
75425bb815Sopenharmony_ci
76425bb815Sopenharmony_ci  lexer_next_token (context_p);
77425bb815Sopenharmony_ci  parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_ARROW);
78425bb815Sopenharmony_ci  scanner_check_directives (context_p, scanner_context_p);
79425bb815Sopenharmony_ci} /* scanner_check_arrow_body */
80425bb815Sopenharmony_ci
81425bb815Sopenharmony_ci/**
82425bb815Sopenharmony_ci * Process arrow function with argument list.
83425bb815Sopenharmony_ci */
84425bb815Sopenharmony_civoid
85425bb815Sopenharmony_ciscanner_check_arrow (parser_context_t *context_p, /**< context */
86425bb815Sopenharmony_ci                     scanner_context_t *scanner_context_p) /**< scanner context */
87425bb815Sopenharmony_ci{
88425bb815Sopenharmony_ci  parser_stack_pop_uint8 (context_p);
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_ci  lexer_next_token (context_p);
91425bb815Sopenharmony_ci
92425bb815Sopenharmony_ci  if (context_p->token.type != LEXER_ARROW
93425bb815Sopenharmony_ci      || (context_p->token.flags & LEXER_WAS_NEWLINE))
94425bb815Sopenharmony_ci  {
95425bb815Sopenharmony_ci    if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
96425bb815Sopenharmony_ci    {
97425bb815Sopenharmony_ci      scanner_add_async_literal (context_p, scanner_context_p);
98425bb815Sopenharmony_ci    }
99425bb815Sopenharmony_ci
100425bb815Sopenharmony_ci    scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
101425bb815Sopenharmony_ci    scanner_pop_literal_pool (context_p, scanner_context_p);
102425bb815Sopenharmony_ci    return;
103425bb815Sopenharmony_ci  }
104425bb815Sopenharmony_ci
105425bb815Sopenharmony_ci  if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
106425bb815Sopenharmony_ci  {
107425bb815Sopenharmony_ci    parser_stack_pop (context_p, NULL, sizeof (lexer_lit_location_t) + 1);
108425bb815Sopenharmony_ci  }
109425bb815Sopenharmony_ci
110425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
111425bb815Sopenharmony_ci  uint16_t status_flags = literal_pool_p->status_flags;
112425bb815Sopenharmony_ci
113425bb815Sopenharmony_ci  status_flags |= SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
114425bb815Sopenharmony_ci  status_flags &= (uint16_t) ~(SCANNER_LITERAL_POOL_IN_WITH
115425bb815Sopenharmony_ci                               | SCANNER_LITERAL_POOL_GENERATOR
116425bb815Sopenharmony_ci                               | SCANNER_LITERAL_POOL_ASYNC);
117425bb815Sopenharmony_ci
118425bb815Sopenharmony_ci  context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
119425bb815Sopenharmony_ci
120425bb815Sopenharmony_ci  if (status_flags & SCANNER_LITERAL_POOL_ASYNC_ARROW)
121425bb815Sopenharmony_ci  {
122425bb815Sopenharmony_ci    status_flags |= SCANNER_LITERAL_POOL_ASYNC;
123425bb815Sopenharmony_ci    context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
124425bb815Sopenharmony_ci  }
125425bb815Sopenharmony_ci
126425bb815Sopenharmony_ci  literal_pool_p->status_flags = status_flags;
127425bb815Sopenharmony_ci
128425bb815Sopenharmony_ci  scanner_filter_arguments (context_p, scanner_context_p);
129425bb815Sopenharmony_ci  scanner_check_arrow_body (context_p, scanner_context_p);
130425bb815Sopenharmony_ci} /* scanner_check_arrow */
131425bb815Sopenharmony_ci
132425bb815Sopenharmony_ci/**
133425bb815Sopenharmony_ci * Process arrow function with a single argument.
134425bb815Sopenharmony_ci */
135425bb815Sopenharmony_civoid
136425bb815Sopenharmony_ciscanner_scan_simple_arrow (parser_context_t *context_p, /**< context */
137425bb815Sopenharmony_ci                           scanner_context_t *scanner_context_p, /**< scanner context */
138425bb815Sopenharmony_ci                           const uint8_t *source_p) /**< identifier end position */
139425bb815Sopenharmony_ci{
140425bb815Sopenharmony_ci  uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION_WITHOUT_ARGUMENTS;
141425bb815Sopenharmony_ci
142425bb815Sopenharmony_ci  context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
143425bb815Sopenharmony_ci
144425bb815Sopenharmony_ci  if (scanner_context_p->async_source_p != NULL)
145425bb815Sopenharmony_ci  {
146425bb815Sopenharmony_ci    JERRY_ASSERT (scanner_context_p->async_source_p == source_p);
147425bb815Sopenharmony_ci
148425bb815Sopenharmony_ci    status_flags |= SCANNER_LITERAL_POOL_ASYNC;
149425bb815Sopenharmony_ci    context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
150425bb815Sopenharmony_ci  }
151425bb815Sopenharmony_ci
152425bb815Sopenharmony_ci  scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
153425bb815Sopenharmony_ci  literal_pool_p->source_p = source_p;
154425bb815Sopenharmony_ci
155425bb815Sopenharmony_ci  lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
156425bb815Sopenharmony_ci  location_p->type |= SCANNER_LITERAL_IS_ARG;
157425bb815Sopenharmony_ci
158425bb815Sopenharmony_ci  /* Skip the => token, which size is two. */
159425bb815Sopenharmony_ci  context_p->source_p += 2;
160425bb815Sopenharmony_ci  PARSER_PLUS_EQUAL_LC (context_p->column, 2);
161425bb815Sopenharmony_ci  context_p->token.flags = (uint8_t) (context_p->token.flags & ~LEXER_NO_SKIP_SPACES);
162425bb815Sopenharmony_ci
163425bb815Sopenharmony_ci  scanner_check_arrow_body (context_p, scanner_context_p);
164425bb815Sopenharmony_ci} /* scanner_scan_simple_arrow */
165425bb815Sopenharmony_ci
166425bb815Sopenharmony_ci/**
167425bb815Sopenharmony_ci * Process the next argument of a might-be arrow function.
168425bb815Sopenharmony_ci */
169425bb815Sopenharmony_civoid
170425bb815Sopenharmony_ciscanner_check_arrow_arg (parser_context_t *context_p, /**< context */
171425bb815Sopenharmony_ci                         scanner_context_t *scanner_context_p) /**< scanner context */
172425bb815Sopenharmony_ci{
173425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
174425bb815Sopenharmony_ci
175425bb815Sopenharmony_ci  const uint8_t *source_p = context_p->source_p;
176425bb815Sopenharmony_ci  bool process_arrow = false;
177425bb815Sopenharmony_ci
178425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
179425bb815Sopenharmony_ci
180425bb815Sopenharmony_ci  if (context_p->token.type == LEXER_THREE_DOTS)
181425bb815Sopenharmony_ci  {
182425bb815Sopenharmony_ci    lexer_next_token (context_p);
183425bb815Sopenharmony_ci  }
184425bb815Sopenharmony_ci
185425bb815Sopenharmony_ci  if (context_p->token.type == LEXER_LITERAL
186425bb815Sopenharmony_ci      && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
187425bb815Sopenharmony_ci  {
188425bb815Sopenharmony_ci    scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
189425bb815Sopenharmony_ci
190425bb815Sopenharmony_ci    if (lexer_check_arrow (context_p))
191425bb815Sopenharmony_ci    {
192425bb815Sopenharmony_ci      process_arrow = true;
193425bb815Sopenharmony_ci    }
194425bb815Sopenharmony_ci    else
195425bb815Sopenharmony_ci    {
196425bb815Sopenharmony_ci      lexer_lit_location_t *argument_literal_p = scanner_append_argument (context_p, scanner_context_p);
197425bb815Sopenharmony_ci
198425bb815Sopenharmony_ci      scanner_detect_eval_call (context_p, scanner_context_p);
199425bb815Sopenharmony_ci
200425bb815Sopenharmony_ci      lexer_next_token (context_p);
201425bb815Sopenharmony_ci
202425bb815Sopenharmony_ci      if (context_p->token.type == LEXER_ASSIGN)
203425bb815Sopenharmony_ci      {
204425bb815Sopenharmony_ci        if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
205425bb815Sopenharmony_ci        {
206425bb815Sopenharmony_ci          JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
207425bb815Sopenharmony_ci          return;
208425bb815Sopenharmony_ci        }
209425bb815Sopenharmony_ci
210425bb815Sopenharmony_ci        scanner_binding_literal_t binding_literal;
211425bb815Sopenharmony_ci        binding_literal.literal_p = argument_literal_p;
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci        parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
214425bb815Sopenharmony_ci        parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
215425bb815Sopenharmony_ci        return;
216425bb815Sopenharmony_ci      }
217425bb815Sopenharmony_ci
218425bb815Sopenharmony_ci      if (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_PAREN)
219425bb815Sopenharmony_ci      {
220425bb815Sopenharmony_ci        return;
221425bb815Sopenharmony_ci      }
222425bb815Sopenharmony_ci    }
223425bb815Sopenharmony_ci  }
224425bb815Sopenharmony_ci  else if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
225425bb815Sopenharmony_ci  {
226425bb815Sopenharmony_ci    scanner_append_hole (context_p, scanner_context_p);
227425bb815Sopenharmony_ci    scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_ARROW_ARG, false);
228425bb815Sopenharmony_ci
229425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_LEFT_BRACE)
230425bb815Sopenharmony_ci    {
231425bb815Sopenharmony_ci      parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
232425bb815Sopenharmony_ci      scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
233425bb815Sopenharmony_ci      return;
234425bb815Sopenharmony_ci    }
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci    parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
237425bb815Sopenharmony_ci    scanner_context_p->mode = SCAN_MODE_BINDING;
238425bb815Sopenharmony_ci    lexer_next_token (context_p);
239425bb815Sopenharmony_ci    return;
240425bb815Sopenharmony_ci  }
241425bb815Sopenharmony_ci
242425bb815Sopenharmony_ci  scanner_pop_literal_pool (context_p, scanner_context_p);
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci  parser_stack_pop_uint8 (context_p);
245425bb815Sopenharmony_ci  parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
246425bb815Sopenharmony_ci
247425bb815Sopenharmony_ci  if (process_arrow)
248425bb815Sopenharmony_ci  {
249425bb815Sopenharmony_ci    scanner_scan_simple_arrow (context_p, scanner_context_p, source_p);
250425bb815Sopenharmony_ci  }
251425bb815Sopenharmony_ci} /* scanner_check_arrow_arg */
252425bb815Sopenharmony_ci
253425bb815Sopenharmony_ci/**
254425bb815Sopenharmony_ci * Detect async functions.
255425bb815Sopenharmony_ci *
256425bb815Sopenharmony_ci * @return true, if async is followed by a function keyword, false otherwise
257425bb815Sopenharmony_ci */
258425bb815Sopenharmony_cibool
259425bb815Sopenharmony_ciscanner_check_async_function (parser_context_t *context_p, /**< context */
260425bb815Sopenharmony_ci                              scanner_context_t *scanner_context_p) /**< scanner context */
261425bb815Sopenharmony_ci{
262425bb815Sopenharmony_ci  JERRY_ASSERT (lexer_token_is_async (context_p));
263425bb815Sopenharmony_ci  JERRY_ASSERT (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION
264425bb815Sopenharmony_ci                || scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW);
265425bb815Sopenharmony_ci  JERRY_ASSERT (scanner_context_p->async_source_p != NULL);
266425bb815Sopenharmony_ci
267425bb815Sopenharmony_ci  lexer_lit_location_t async_literal = context_p->token.lit_location;
268425bb815Sopenharmony_ci
269425bb815Sopenharmony_ci  lexer_next_token (context_p);
270425bb815Sopenharmony_ci
271425bb815Sopenharmony_ci  if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
272425bb815Sopenharmony_ci  {
273425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_KEYW_FUNCTION)
274425bb815Sopenharmony_ci    {
275425bb815Sopenharmony_ci      return true;
276425bb815Sopenharmony_ci    }
277425bb815Sopenharmony_ci
278425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_LITERAL
279425bb815Sopenharmony_ci        && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
280425bb815Sopenharmony_ci    {
281425bb815Sopenharmony_ci      if (!lexer_check_arrow (context_p))
282425bb815Sopenharmony_ci      {
283425bb815Sopenharmony_ci        scanner_raise_error (context_p);
284425bb815Sopenharmony_ci      }
285425bb815Sopenharmony_ci
286425bb815Sopenharmony_ci      scanner_scan_simple_arrow (context_p, scanner_context_p, scanner_context_p->async_source_p);
287425bb815Sopenharmony_ci      scanner_context_p->async_source_p = NULL;
288425bb815Sopenharmony_ci      return false;
289425bb815Sopenharmony_ci    }
290425bb815Sopenharmony_ci
291425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_LEFT_PAREN)
292425bb815Sopenharmony_ci    {
293425bb815Sopenharmony_ci      parser_stack_push (context_p, &async_literal, sizeof (lexer_lit_location_t));
294425bb815Sopenharmony_ci      parser_stack_push_uint8 (context_p, SCAN_STACK_USE_ASYNC);
295425bb815Sopenharmony_ci      return false;
296425bb815Sopenharmony_ci    }
297425bb815Sopenharmony_ci  }
298425bb815Sopenharmony_ci
299425bb815Sopenharmony_ci  lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
300425bb815Sopenharmony_ci                                                                     scanner_context_p->active_literal_pool_p,
301425bb815Sopenharmony_ci                                                                     &async_literal);
302425bb815Sopenharmony_ci  lit_location_p->type |= SCANNER_LITERAL_IS_USED;
303425bb815Sopenharmony_ci
304425bb815Sopenharmony_ci  if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
305425bb815Sopenharmony_ci  {
306425bb815Sopenharmony_ci    lit_location_p->type |= SCANNER_LITERAL_NO_REG;
307425bb815Sopenharmony_ci  }
308425bb815Sopenharmony_ci
309425bb815Sopenharmony_ci  scanner_context_p->async_source_p = NULL;
310425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
311425bb815Sopenharmony_ci  return false;
312425bb815Sopenharmony_ci} /* scanner_check_async_function */
313425bb815Sopenharmony_ci
314425bb815Sopenharmony_ci/**
315425bb815Sopenharmony_ci * Check whether the statement of an if/else construct is a function statement.
316425bb815Sopenharmony_ci */
317425bb815Sopenharmony_civoid
318425bb815Sopenharmony_ciscanner_check_function_after_if (parser_context_t *context_p, /**< context */
319425bb815Sopenharmony_ci                                 scanner_context_t *scanner_context_p) /**< scanner context */
320425bb815Sopenharmony_ci{
321425bb815Sopenharmony_ci  lexer_next_token (context_p);
322425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_STATEMENT;
323425bb815Sopenharmony_ci
324425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (context_p->token.type == LEXER_KEYW_FUNCTION))
325425bb815Sopenharmony_ci  {
326425bb815Sopenharmony_ci    scanner_literal_pool_t *literal_pool_p;
327425bb815Sopenharmony_ci    literal_pool_p = scanner_push_literal_pool (context_p,
328425bb815Sopenharmony_ci                                                scanner_context_p,
329425bb815Sopenharmony_ci                                                SCANNER_LITERAL_POOL_BLOCK);
330425bb815Sopenharmony_ci
331425bb815Sopenharmony_ci    literal_pool_p->source_p = context_p->source_p;
332425bb815Sopenharmony_ci    parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK);
333425bb815Sopenharmony_ci  }
334425bb815Sopenharmony_ci} /* scanner_check_function_after_if */
335425bb815Sopenharmony_ci
336425bb815Sopenharmony_ci/**
337425bb815Sopenharmony_ci * Arrow types for scanner_scan_bracket() function.
338425bb815Sopenharmony_ci */
339425bb815Sopenharmony_citypedef enum
340425bb815Sopenharmony_ci{
341425bb815Sopenharmony_ci  SCANNER_SCAN_BRACKET_NO_ARROW, /**< not an arrow function */
342425bb815Sopenharmony_ci  SCANNER_SCAN_BRACKET_SIMPLE_ARROW, /**< simple arrow function */
343425bb815Sopenharmony_ci  SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG, /**< arrow function with one argument */
344425bb815Sopenharmony_ci} scanner_scan_bracket_arrow_type_t;
345425bb815Sopenharmony_ci
346425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
347425bb815Sopenharmony_ci
348425bb815Sopenharmony_ci/**
349425bb815Sopenharmony_ci * Scan bracketed expressions.
350425bb815Sopenharmony_ci */
351425bb815Sopenharmony_civoid
352425bb815Sopenharmony_ciscanner_scan_bracket (parser_context_t *context_p, /**< context */
353425bb815Sopenharmony_ci                      scanner_context_t *scanner_context_p) /**< scanner context */
354425bb815Sopenharmony_ci{
355425bb815Sopenharmony_ci  size_t depth = 0;
356425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
357425bb815Sopenharmony_ci  const uint8_t *arrow_source_p;
358425bb815Sopenharmony_ci  const uint8_t *async_source_p = NULL;
359425bb815Sopenharmony_ci  scanner_scan_bracket_arrow_type_t arrow_type = SCANNER_SCAN_BRACKET_NO_ARROW;
360425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
361425bb815Sopenharmony_ci
362425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_LEFT_PAREN);
363425bb815Sopenharmony_ci
364425bb815Sopenharmony_ci  do
365425bb815Sopenharmony_ci  {
366425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
367425bb815Sopenharmony_ci    arrow_source_p = context_p->source_p;
368425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
369425bb815Sopenharmony_ci    depth++;
370425bb815Sopenharmony_ci    lexer_next_token (context_p);
371425bb815Sopenharmony_ci  }
372425bb815Sopenharmony_ci  while (context_p->token.type == LEXER_LEFT_PAREN);
373425bb815Sopenharmony_ci
374425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
375425bb815Sopenharmony_ci
376425bb815Sopenharmony_ci  switch (context_p->token.type)
377425bb815Sopenharmony_ci  {
378425bb815Sopenharmony_ci    case LEXER_LITERAL:
379425bb815Sopenharmony_ci    {
380425bb815Sopenharmony_ci      if (context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
381425bb815Sopenharmony_ci      {
382425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
383425bb815Sopenharmony_ci        arrow_source_p = NULL;
384425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
385425bb815Sopenharmony_ci        break;
386425bb815Sopenharmony_ci      }
387425bb815Sopenharmony_ci
388425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
389425bb815Sopenharmony_ci      const uint8_t *source_p = context_p->source_p;
390425bb815Sopenharmony_ci
391425bb815Sopenharmony_ci      if (lexer_check_arrow (context_p))
392425bb815Sopenharmony_ci      {
393425bb815Sopenharmony_ci        arrow_source_p = source_p;
394425bb815Sopenharmony_ci        arrow_type = SCANNER_SCAN_BRACKET_SIMPLE_ARROW;
395425bb815Sopenharmony_ci        break;
396425bb815Sopenharmony_ci      }
397425bb815Sopenharmony_ci
398425bb815Sopenharmony_ci      size_t total_depth = depth;
399425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
400425bb815Sopenharmony_ci
401425bb815Sopenharmony_ci      while (depth > 0 && lexer_check_next_character (context_p, LIT_CHAR_RIGHT_PAREN))
402425bb815Sopenharmony_ci      {
403425bb815Sopenharmony_ci        lexer_consume_next_character (context_p);
404425bb815Sopenharmony_ci        depth--;
405425bb815Sopenharmony_ci      }
406425bb815Sopenharmony_ci
407425bb815Sopenharmony_ci      if (context_p->token.keyword_type == LEXER_KEYW_EVAL
408425bb815Sopenharmony_ci          && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
409425bb815Sopenharmony_ci      {
410425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
411425bb815Sopenharmony_ci        /* A function call cannot be an eval function. */
412425bb815Sopenharmony_ci        arrow_source_p = NULL;
413425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
414425bb815Sopenharmony_ci
415425bb815Sopenharmony_ci        scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
416425bb815Sopenharmony_ci        break;
417425bb815Sopenharmony_ci      }
418425bb815Sopenharmony_ci
419425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
420425bb815Sopenharmony_ci      if (total_depth == depth)
421425bb815Sopenharmony_ci      {
422425bb815Sopenharmony_ci        if (lexer_check_arrow_param (context_p))
423425bb815Sopenharmony_ci        {
424425bb815Sopenharmony_ci          JERRY_ASSERT (depth > 0);
425425bb815Sopenharmony_ci          depth--;
426425bb815Sopenharmony_ci          break;
427425bb815Sopenharmony_ci        }
428425bb815Sopenharmony_ci
429425bb815Sopenharmony_ci        if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
430425bb815Sopenharmony_ci        {
431425bb815Sopenharmony_ci          async_source_p = source_p;
432425bb815Sopenharmony_ci        }
433425bb815Sopenharmony_ci      }
434425bb815Sopenharmony_ci      else if (depth == total_depth - 1)
435425bb815Sopenharmony_ci      {
436425bb815Sopenharmony_ci        if (lexer_check_arrow (context_p))
437425bb815Sopenharmony_ci        {
438425bb815Sopenharmony_ci          arrow_type = SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG;
439425bb815Sopenharmony_ci          break;
440425bb815Sopenharmony_ci        }
441425bb815Sopenharmony_ci
442425bb815Sopenharmony_ci        if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
443425bb815Sopenharmony_ci        {
444425bb815Sopenharmony_ci          scanner_add_async_literal (context_p, scanner_context_p);
445425bb815Sopenharmony_ci        }
446425bb815Sopenharmony_ci      }
447425bb815Sopenharmony_ci
448425bb815Sopenharmony_ci      arrow_source_p = NULL;
449425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
450425bb815Sopenharmony_ci      break;
451425bb815Sopenharmony_ci    }
452425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
453425bb815Sopenharmony_ci    case LEXER_THREE_DOTS:
454425bb815Sopenharmony_ci    case LEXER_LEFT_SQUARE:
455425bb815Sopenharmony_ci    case LEXER_LEFT_BRACE:
456425bb815Sopenharmony_ci    case LEXER_RIGHT_PAREN:
457425bb815Sopenharmony_ci    {
458425bb815Sopenharmony_ci      JERRY_ASSERT (depth > 0);
459425bb815Sopenharmony_ci      depth--;
460425bb815Sopenharmony_ci      break;
461425bb815Sopenharmony_ci    }
462425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
463425bb815Sopenharmony_ci    default:
464425bb815Sopenharmony_ci    {
465425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
466425bb815Sopenharmony_ci      arrow_source_p = NULL;
467425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
468425bb815Sopenharmony_ci      break;
469425bb815Sopenharmony_ci    }
470425bb815Sopenharmony_ci  }
471425bb815Sopenharmony_ci
472425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
473425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL)
474425bb815Sopenharmony_ci      && (arrow_source_p == NULL || depth > 0))
475425bb815Sopenharmony_ci  {
476425bb815Sopenharmony_ci    scanner_context_p->async_source_p = NULL;
477425bb815Sopenharmony_ci  }
478425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
479425bb815Sopenharmony_ci
480425bb815Sopenharmony_ci  while (depth > 0)
481425bb815Sopenharmony_ci  {
482425bb815Sopenharmony_ci    parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
483425bb815Sopenharmony_ci    depth--;
484425bb815Sopenharmony_ci  }
485425bb815Sopenharmony_ci
486425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
487425bb815Sopenharmony_ci  if (arrow_source_p != NULL)
488425bb815Sopenharmony_ci  {
489425bb815Sopenharmony_ci    JERRY_ASSERT (async_source_p == NULL);
490425bb815Sopenharmony_ci
491425bb815Sopenharmony_ci    if (arrow_type == SCANNER_SCAN_BRACKET_SIMPLE_ARROW)
492425bb815Sopenharmony_ci    {
493425bb815Sopenharmony_ci      scanner_scan_simple_arrow (context_p, scanner_context_p, arrow_source_p);
494425bb815Sopenharmony_ci      return;
495425bb815Sopenharmony_ci    }
496425bb815Sopenharmony_ci
497425bb815Sopenharmony_ci    parser_stack_push_uint8 (context_p, SCAN_STACK_ARROW_ARGUMENTS);
498425bb815Sopenharmony_ci
499425bb815Sopenharmony_ci    uint16_t status_flags = 0;
500425bb815Sopenharmony_ci
501425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (scanner_context_p->async_source_p != NULL))
502425bb815Sopenharmony_ci    {
503425bb815Sopenharmony_ci      status_flags |= SCANNER_LITERAL_POOL_ASYNC_ARROW;
504425bb815Sopenharmony_ci      arrow_source_p = scanner_context_p->async_source_p;
505425bb815Sopenharmony_ci      scanner_context_p->async_source_p = NULL;
506425bb815Sopenharmony_ci    }
507425bb815Sopenharmony_ci
508425bb815Sopenharmony_ci    scanner_literal_pool_t *literal_pool_p;
509425bb815Sopenharmony_ci    literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
510425bb815Sopenharmony_ci    literal_pool_p->source_p = arrow_source_p;
511425bb815Sopenharmony_ci
512425bb815Sopenharmony_ci    if (arrow_type == SCANNER_SCAN_BRACKET_ARROW_WITH_ONE_ARG)
513425bb815Sopenharmony_ci    {
514425bb815Sopenharmony_ci      scanner_append_argument (context_p, scanner_context_p);
515425bb815Sopenharmony_ci      scanner_detect_eval_call (context_p, scanner_context_p);
516425bb815Sopenharmony_ci
517425bb815Sopenharmony_ci      context_p->token.type = LEXER_RIGHT_PAREN;
518425bb815Sopenharmony_ci      scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
519425bb815Sopenharmony_ci    }
520425bb815Sopenharmony_ci    else if (context_p->token.type == LEXER_RIGHT_PAREN)
521425bb815Sopenharmony_ci    {
522425bb815Sopenharmony_ci      scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
523425bb815Sopenharmony_ci    }
524425bb815Sopenharmony_ci    else
525425bb815Sopenharmony_ci    {
526425bb815Sopenharmony_ci      scanner_check_arrow_arg (context_p, scanner_context_p);
527425bb815Sopenharmony_ci    }
528425bb815Sopenharmony_ci  }
529425bb815Sopenharmony_ci  else if (JERRY_UNLIKELY (async_source_p != NULL))
530425bb815Sopenharmony_ci  {
531425bb815Sopenharmony_ci    scanner_context_p->async_source_p = async_source_p;
532425bb815Sopenharmony_ci    scanner_check_async_function (context_p, scanner_context_p);
533425bb815Sopenharmony_ci  }
534425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
535425bb815Sopenharmony_ci} /* scanner_scan_bracket */
536425bb815Sopenharmony_ci
537425bb815Sopenharmony_ci/**
538425bb815Sopenharmony_ci * Check directives before a source block.
539425bb815Sopenharmony_ci */
540425bb815Sopenharmony_civoid
541425bb815Sopenharmony_ciscanner_check_directives (parser_context_t *context_p, /**< context */
542425bb815Sopenharmony_ci                          scanner_context_t *scanner_context_p) /**< scanner context */
543425bb815Sopenharmony_ci{
544425bb815Sopenharmony_ci  scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
545425bb815Sopenharmony_ci
546425bb815Sopenharmony_ci  while (context_p->token.type == LEXER_LITERAL
547425bb815Sopenharmony_ci         && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
548425bb815Sopenharmony_ci  {
549425bb815Sopenharmony_ci    bool is_use_strict = false;
550425bb815Sopenharmony_ci
551425bb815Sopenharmony_ci    if (lexer_string_is_use_strict (context_p)
552425bb815Sopenharmony_ci        && !(context_p->status_flags & PARSER_IS_STRICT))
553425bb815Sopenharmony_ci    {
554425bb815Sopenharmony_ci      is_use_strict = true;
555425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_IS_STRICT;
556425bb815Sopenharmony_ci    }
557425bb815Sopenharmony_ci
558425bb815Sopenharmony_ci    lexer_next_token (context_p);
559425bb815Sopenharmony_ci
560425bb815Sopenharmony_ci    if (!lexer_string_is_directive (context_p))
561425bb815Sopenharmony_ci    {
562425bb815Sopenharmony_ci      if (is_use_strict)
563425bb815Sopenharmony_ci      {
564425bb815Sopenharmony_ci        context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
565425bb815Sopenharmony_ci      }
566425bb815Sopenharmony_ci
567425bb815Sopenharmony_ci      /* The string is part of an expression statement. */
568425bb815Sopenharmony_ci      scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
569425bb815Sopenharmony_ci      break;
570425bb815Sopenharmony_ci    }
571425bb815Sopenharmony_ci
572425bb815Sopenharmony_ci    if (is_use_strict)
573425bb815Sopenharmony_ci    {
574425bb815Sopenharmony_ci      scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
575425bb815Sopenharmony_ci    }
576425bb815Sopenharmony_ci
577425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_SEMICOLON)
578425bb815Sopenharmony_ci    {
579425bb815Sopenharmony_ci      lexer_next_token (context_p);
580425bb815Sopenharmony_ci    }
581425bb815Sopenharmony_ci  }
582425bb815Sopenharmony_ci} /* scanner_check_directives */
583425bb815Sopenharmony_ci
584425bb815Sopenharmony_ci/**
585425bb815Sopenharmony_ci * @}
586425bb815Sopenharmony_ci * @}
587425bb815Sopenharmony_ci * @}
588425bb815Sopenharmony_ci */
589425bb815Sopenharmony_ci
590425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */
591