mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Notable changes:
- Updated and the port API interface, new functions have been added
and some have been changed. The port library is now cleaned up to
not have any dependency on jerry-core, as it should be. The port library
is now strictly a collection of functions that implement
embedding/platform specific behavior.
- The default port implementation has been split for windows and unix.
Implemented port functions have been categorized and reorganized,
and marked with attribute((weak)) for better reusability.
- External context allocation has been moved to the port API instead
of a core API callback. The iterface has also been extended with a
function to free the allocated context. When external context is
enabled, jerry_init now automatically calls the port implementation
to allocate the context and jerry_cleanup automatically calls the port
to free the context.
- jerry_port_log has been changed to no longer require formatting to
be implemented by the port. The reason beind this is that it was vague what
format specifiers were used by the engine, and in what manner. The port
function now takes a zero-terminated string, and should only implement
how the string should be logged.
- Logging and log message formatting is now handled by the core jerry library
where it can be implemented as necessary. Logging can be done through a new
core API function, which uses the port to output the final log message.
- Log level has been moved into jerry-core, and an API function has
been added to set the log level. It should be the library that
filters log messages based on the requested log level, instead of
logging everything and requiring the user to do so.
- Module resolving logic has been moved into jerry-core. There's no
reason to have it in the port library and requiring embedders to
duplicate the code. It also added an unnecessary dependency on
jerry-core to the port. Platform specific behavior is still used through
the port API, like resolving module specifiers, and reading source file
contents. If necessary, the resolving logic can still be overridden as
previously.
- The jerry-ext library has also been cleaned up, and many utility
functions have been added that previously were implemented in
jerry-main. This allows easier reusability for some common operations,
like printing unhandled exceptions or providing a repl console.
- Debugger interaction with logged/printed messages has been fixed, so
that it's no longer the port implementations responsibility to send
the output to the debugger, as the port should have no notion of what a
debugger is. The printing and logging functions will now pass the
result message to the debugger, if connected.
- Cleaned up TZA handling in the date port implementation, and simplified
the API function prototype.
- Moved property access helper functions that use ASCII strings as
keys from jerry-ext to the core API.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai@inf.u-szeged.hu
3972 lines
126 KiB
C
3972 lines
126 KiB
C
/* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "jcontext.h"
|
|
#include "js-parser-internal.h"
|
|
#include "js-scanner-internal.h"
|
|
#include "lit-char-helpers.h"
|
|
|
|
#if JERRY_PARSER
|
|
|
|
/** \addtogroup parser Parser
|
|
* @{
|
|
*
|
|
* \addtogroup jsparser JavaScript
|
|
* @{
|
|
*
|
|
* \addtogroup jsparser_scanner Scanner
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Scan return types.
|
|
*/
|
|
typedef enum
|
|
{
|
|
SCAN_NEXT_TOKEN, /**< get next token after return */
|
|
SCAN_KEEP_TOKEN, /**< keep the current token after return */
|
|
} scan_return_types_t;
|
|
|
|
/**
|
|
* Checks whether token type is "of".
|
|
*/
|
|
#if JERRY_ESNEXT
|
|
#define SCANNER_IDENTIFIER_IS_OF() (lexer_token_is_identifier (context_p, "of", 2))
|
|
#else /* !JERRY_ESNEXT */
|
|
#define SCANNER_IDENTIFIER_IS_OF() (false)
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
#if JERRY_ESNEXT
|
|
|
|
JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_GENERATOR)
|
|
== SCAN_STACK_COMPUTED_GENERATOR,
|
|
scanner_invalid_conversion_from_literal_pool_generator_to_computed_generator);
|
|
JERRY_STATIC_ASSERT (SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (SCANNER_LITERAL_POOL_ASYNC) == SCAN_STACK_COMPUTED_ASYNC,
|
|
scanner_invalid_conversion_from_literal_pool_async_to_computed_async);
|
|
|
|
JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_GENERATOR)
|
|
== SCANNER_LITERAL_POOL_GENERATOR,
|
|
scanner_invalid_conversion_from_computed_generator_to_literal_pool_generator);
|
|
JERRY_STATIC_ASSERT (SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (SCAN_STACK_COMPUTED_ASYNC) == SCANNER_LITERAL_POOL_ASYNC,
|
|
scanner_invalid_conversion_from_computed_async_to_literal_pool_async);
|
|
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
/**
|
|
* Change scanner mode from primary expression to post primary expression.
|
|
*
|
|
* @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
|
|
*/
|
|
static scan_return_types_t
|
|
scanner_primary_to_post_primary_expression (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p) /* scanner context */
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (JERRY_UNLIKELY (context_p->stack_top_uint8 == SCAN_STACK_CLASS_FIELD_INITIALIZER
|
|
&& (context_p->status_flags & PARSER_IS_STRICT)))
|
|
{
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_CHECK_KEYWORDS | LEXER_PARSE_NO_STRICT_IDENT_ERROR);
|
|
|
|
if (context_p->token.type == LEXER_LITERAL && lexer_compare_literal_to_string (context_p, "static", 6))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
}
|
|
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
JERRY_UNUSED (context_p);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
} /* scanner_primary_to_post_primary_expression */
|
|
|
|
/**
|
|
* Scan primary expression.
|
|
*
|
|
* @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
|
|
*/
|
|
static scan_return_types_t
|
|
scanner_scan_primary_expression (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p, /* scanner context */
|
|
lexer_token_type_t type, /**< current token type */
|
|
scan_stack_modes_t stack_top) /**< current stack top */
|
|
{
|
|
switch (type)
|
|
{
|
|
case LEXER_KEYW_NEW:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (scanner_try_scan_new_target (context_p))
|
|
{
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
break;
|
|
}
|
|
case LEXER_DIVIDE:
|
|
case LEXER_ASSIGN_DIVIDE:
|
|
{
|
|
lexer_construct_regexp_object (context_p, true);
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
case LEXER_KEYW_FUNCTION:
|
|
{
|
|
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
|
#if JERRY_MODULE_SYSTEM
|
|
bool is_export_default = stack_top == SCAN_STACK_EXPORT_DEFAULT;
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
#if JERRY_ESNEXT
|
|
if (scanner_context_p->async_source_p != NULL)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
}
|
|
|
|
if (lexer_consume_generator (context_p))
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (is_export_default)
|
|
{
|
|
lexer_lit_location_t *location_p;
|
|
location_p = scanner_add_custom_literal (context_p,
|
|
scanner_context_p->active_literal_pool_p->prev_p,
|
|
&context_p->token.lit_location);
|
|
|
|
scanner_detect_invalid_let (context_p, location_p);
|
|
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
lexer_next_token (context_p);
|
|
}
|
|
#if JERRY_MODULE_SYSTEM
|
|
else if (is_export_default)
|
|
{
|
|
lexer_lit_location_t *location_p;
|
|
location_p = scanner_add_custom_literal (context_p,
|
|
scanner_context_p->active_literal_pool_p->prev_p,
|
|
&lexer_default_literal);
|
|
location_p->type |= SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LET;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_EXPRESSION);
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_LEFT_PAREN:
|
|
{
|
|
scanner_scan_bracket (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_LEFT_SQUARE:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
case LEXER_LEFT_BRACE:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_NONE, false);
|
|
parser_stack_push_uint8 (context_p, 0);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_HASHMARK:
|
|
{
|
|
if (!lexer_scan_private_identifier (context_p))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_TEMPLATE_LITERAL:
|
|
{
|
|
if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_TEMPLATE_STRING);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
/* The string is a normal string literal. */
|
|
/* FALLTHRU */
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case LEXER_LITERAL:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
const uint8_t *source_p = context_p->source_p;
|
|
|
|
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL && lexer_check_arrow (context_p))
|
|
{
|
|
scanner_scan_simple_arrow (context_p, scanner_context_p, source_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
|
|
{
|
|
scanner_context_p->async_source_p = source_p;
|
|
scanner_check_async_function (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (stack_top == SCAN_STACK_EXPORT_DEFAULT)
|
|
{
|
|
lexer_lit_location_t *location_p = scanner_add_literal (context_p, scanner_context_p);
|
|
location_p->type |= (SCANNER_LITERAL_IS_USED | SCANNER_LITERAL_IS_VAR);
|
|
scanner_detect_eval_call (context_p, scanner_context_p);
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
scanner_add_reference (context_p, scanner_context_p);
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
case LEXER_KEYW_THIS:
|
|
case LEXER_LIT_TRUE:
|
|
case LEXER_LIT_FALSE:
|
|
case LEXER_LIT_NULL:
|
|
{
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_KEYW_SUPER:
|
|
{
|
|
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE;
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
case LEXER_KEYW_CLASS:
|
|
{
|
|
scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_EXPRESSION);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case LEXER_RIGHT_SQUARE:
|
|
{
|
|
if (stack_top != SCAN_STACK_ARRAY_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_THREE_DOTS:
|
|
{
|
|
/* Elision or spread arguments */
|
|
if (stack_top != SCAN_STACK_PAREN_EXPRESSION && stack_top != SCAN_STACK_ARRAY_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case LEXER_COMMA:
|
|
{
|
|
if (stack_top != SCAN_STACK_ARRAY_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_BINDING;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_KEYW_YIELD:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (lexer_check_yield_no_arg (context_p))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
#if JERRY_MODULE_SYSTEM
|
|
case LEXER_KEYW_IMPORT:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_DOT)
|
|
{
|
|
scanner_check_import_meta (context_p);
|
|
}
|
|
else if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
case LEXER_RIGHT_PAREN:
|
|
{
|
|
if (stack_top == SCAN_STACK_PAREN_EXPRESSION)
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
scanner_add_async_literal (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
return scanner_primary_to_post_primary_expression (context_p, scanner_context_p);
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
default:
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
}
|
|
return SCAN_NEXT_TOKEN;
|
|
} /* scanner_scan_primary_expression */
|
|
|
|
/**
|
|
* Scan the tokens after the primary expression.
|
|
*
|
|
* @return true for break, false for fall through
|
|
*/
|
|
static bool
|
|
scanner_scan_post_primary_expression (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p, /**< scanner context */
|
|
lexer_token_type_t type, /**< current token type */
|
|
scan_stack_modes_t stack_top) /**< current stack top */
|
|
{
|
|
switch (type)
|
|
{
|
|
case LEXER_DOT:
|
|
{
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_HASHMARK)
|
|
{
|
|
context_p->token.flags |= LEXER_NO_SKIP_SPACES;
|
|
lexer_next_token (context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
case LEXER_LEFT_PAREN:
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PAREN_EXPRESSION);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return true;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_TEMPLATE_LITERAL:
|
|
{
|
|
if (JERRY_UNLIKELY (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_TAGGED_TEMPLATE_LITERAL);
|
|
}
|
|
return true;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case LEXER_LEFT_SQUARE:
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PROPERTY_ACCESSOR);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return true;
|
|
}
|
|
case LEXER_INCREASE:
|
|
case LEXER_DECREASE:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
|
|
if (context_p->token.flags & LEXER_WAS_NEWLINE)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
|
|
if (type != LEXER_QUESTION_MARK)
|
|
{
|
|
break;
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
case LEXER_QUESTION_MARK:
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_COLON_EXPRESSION);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return true;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (LEXER_IS_BINARY_OP_TOKEN (type) && (type != LEXER_KEYW_IN || !SCANNER_IS_FOR_START (stack_top)))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
} /* scanner_scan_post_primary_expression */
|
|
|
|
/**
|
|
* Scan the tokens after the primary expression.
|
|
*
|
|
* @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
|
|
*/
|
|
static scan_return_types_t
|
|
scanner_scan_primary_expression_end (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p, /**< scanner context */
|
|
lexer_token_type_t type, /**< current token type */
|
|
scan_stack_modes_t stack_top) /**< current stack top */
|
|
{
|
|
if (type == LEXER_COMMA)
|
|
{
|
|
switch (stack_top)
|
|
{
|
|
case SCAN_STACK_VAR:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_LET:
|
|
case SCAN_STACK_CONST:
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_FOR_VAR_START:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_FOR_LET_START:
|
|
case SCAN_STACK_FOR_CONST_START:
|
|
#endif /* JERRY_ESNEXT */
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_COLON_EXPRESSION:
|
|
{
|
|
scanner_raise_error (context_p);
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_BINDING_INIT:
|
|
case SCAN_STACK_BINDING_LIST_INIT:
|
|
{
|
|
break;
|
|
}
|
|
case SCAN_STACK_ARROW_ARGUMENTS:
|
|
{
|
|
lexer_next_token (context_p);
|
|
scanner_check_arrow_arg (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_ARROW_EXPRESSION:
|
|
{
|
|
break;
|
|
}
|
|
case SCAN_STACK_CLASS_FIELD_INITIALIZER:
|
|
{
|
|
scanner_raise_error (context_p);
|
|
break;
|
|
}
|
|
case SCAN_STACK_FUNCTION_PARAMETERS:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
|
|
parser_stack_pop_uint8 (context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_ARRAY_LITERAL:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_BINDING;
|
|
}
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_OBJECT_LITERAL:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
default:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (stack_top)
|
|
{
|
|
case SCAN_STACK_WITH_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
uint16_t status_flags = scanner_context_p->active_literal_pool_p->status_flags;
|
|
parser_stack_push_uint8 (context_p, (status_flags & SCANNER_LITERAL_POOL_IN_WITH) ? 1 : 0);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_WITH_STATEMENT);
|
|
status_flags |= SCANNER_LITERAL_POOL_IN_WITH;
|
|
scanner_context_p->active_literal_pool_p->status_flags = status_flags;
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_DO_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_WHILE_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_source_start_t source_start;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
|
|
scanner_location_info_t *location_info_p;
|
|
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
source_start.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
location_info_p->info.type = SCANNER_TYPE_WHILE;
|
|
|
|
scanner_get_location (&location_info_p->location, context_p);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_PAREN_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_USE_ASYNC)
|
|
{
|
|
scanner_add_async_literal (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_STATEMENT_WITH_EXPR:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_IF_STATEMENT)
|
|
{
|
|
scanner_check_function_after_if (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_BINDING_LIST_INIT:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
|
|
|
scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p;
|
|
|
|
while (item_p != NULL)
|
|
{
|
|
if (item_p->literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
item_p->literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
}
|
|
item_p = item_p->next_p;
|
|
}
|
|
|
|
scanner_pop_binding_list (scanner_context_p);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_BINDING_INIT:
|
|
{
|
|
scanner_binding_literal_t binding_literal;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
|
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_ARRAY_LITERAL
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_LET || context_p->stack_top_uint8 == SCAN_STACK_CONST
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_LET_START
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FOR_CONST_START
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PARAMETERS
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_ARROW_ARGUMENTS);
|
|
|
|
JERRY_ASSERT (SCANNER_NEEDS_BINDING_LIST (scanner_context_p->binding_type)
|
|
|| (stack_top != SCAN_STACK_ARRAY_LITERAL && stack_top != SCAN_STACK_OBJECT_LITERAL));
|
|
|
|
if (binding_literal.literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
binding_literal.literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_VAR:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_LET:
|
|
case SCAN_STACK_CONST:
|
|
#endif /* JERRY_ESNEXT */
|
|
{
|
|
#if JERRY_MODULE_SYSTEM
|
|
scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_FOR_VAR_START:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_FOR_LET_START:
|
|
case SCAN_STACK_FOR_CONST_START:
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_FOR_START:
|
|
{
|
|
if (type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ())
|
|
{
|
|
scanner_for_statement_t for_statement;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
|
|
scanner_location_info_t *location_info;
|
|
location_info = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
for_statement.u.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
#if JERRY_ESNEXT
|
|
location_info->info.type = (type == LEXER_KEYW_IN) ? SCANNER_TYPE_FOR_IN : SCANNER_TYPE_FOR_OF;
|
|
|
|
if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK_EARLY);
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
location_info->info.type = SCANNER_TYPE_FOR_IN;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_get_location (&location_info->location, context_p);
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_STATEMENT_WITH_EXPR);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
if (type != LEXER_SEMICOLON)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_for_statement_t for_statement;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, NULL, sizeof (scanner_for_statement_t));
|
|
|
|
#if JERRY_ESNEXT
|
|
if (stack_top == SCAN_STACK_FOR_LET_START || stack_top == SCAN_STACK_FOR_CONST_START)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_PRIVATE_BLOCK);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
for_statement.u.source_p = context_p->source_p;
|
|
parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_CONDITION);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_SEMICOLON)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
type = LEXER_SEMICOLON;
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_STACK_FOR_CONDITION:
|
|
{
|
|
if (type != LEXER_SEMICOLON)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_for_statement_t for_statement;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
|
|
scanner_for_info_t *for_info_p;
|
|
for_info_p =
|
|
(scanner_for_info_t *) scanner_insert_info (context_p, for_statement.u.source_p, sizeof (scanner_for_info_t));
|
|
for_info_p->info.type = SCANNER_TYPE_FOR;
|
|
|
|
scanner_get_location (&for_info_p->expression_location, context_p);
|
|
for_info_p->end_location.source_p = NULL;
|
|
|
|
for_statement.u.for_info_p = for_info_p;
|
|
|
|
parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FOR_EXPRESSION);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
type = LEXER_RIGHT_PAREN;
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_STACK_FOR_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_for_statement_t for_statement;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
|
|
scanner_get_location (&for_statement.u.for_info_p->end_location, context_p);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_SWITCH_EXPRESSION:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = context_p->source_p - 1;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
scanner_switch_statement_t switch_statement = scanner_context_p->active_switch_statement;
|
|
parser_stack_push (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_SWITCH_BLOCK);
|
|
|
|
scanner_switch_info_t *switch_info_p;
|
|
switch_info_p =
|
|
(scanner_switch_info_t *) scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_switch_info_t));
|
|
switch_info_p->info.type = SCANNER_TYPE_SWITCH;
|
|
switch_info_p->case_p = NULL;
|
|
scanner_context_p->active_switch_statement.last_case_p = &switch_info_p->case_p;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_KEYW_CASE
|
|
&& context_p->token.type != LEXER_KEYW_DEFAULT)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_CASE_STATEMENT:
|
|
{
|
|
if (type != LEXER_COLON)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_source_start_t source_start;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
|
|
scanner_location_info_t *location_info_p;
|
|
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
source_start.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
location_info_p->info.type = SCANNER_TYPE_CASE;
|
|
|
|
scanner_get_location (&location_info_p->location, context_p);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_COLON_EXPRESSION:
|
|
{
|
|
if (type != LEXER_COLON)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
parser_stack_pop_uint8 (context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_ARRAY_LITERAL:
|
|
case SCAN_STACK_OBJECT_LITERAL:
|
|
{
|
|
if ((stack_top == SCAN_STACK_ARRAY_LITERAL && type != LEXER_RIGHT_SQUARE)
|
|
|| (stack_top == SCAN_STACK_OBJECT_LITERAL && type != LEXER_RIGHT_BRACE))
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_source_start_t source_start;
|
|
uint8_t binding_type = scanner_context_p->binding_type;
|
|
uint8_t object_literal_flags = 0;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (stack_top == SCAN_STACK_OBJECT_LITERAL)
|
|
{
|
|
object_literal_flags = context_p->stack_top_uint8;
|
|
parser_stack_pop_uint8 (context_p);
|
|
}
|
|
|
|
scanner_context_p->binding_type = context_p->stack_top_uint8;
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
|
|
|
if (binding_type == SCANNER_BINDING_CATCH && stack_top == SCAN_STACK_CATCH_STATEMENT)
|
|
{
|
|
scanner_pop_binding_list (scanner_context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (object_literal_flags != 0)
|
|
{
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
|
info_p->u8_arg = object_literal_flags;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
if (stack_top == SCAN_STACK_FOR_START_PATTERN)
|
|
{
|
|
JERRY_ASSERT (binding_type == SCANNER_BINDING_NONE);
|
|
|
|
parser_stack_change_last_uint8 (context_p, SCAN_STACK_FOR_START);
|
|
|
|
if (context_p->token.type == LEXER_KEYW_IN || SCANNER_IDENTIFIER_IS_OF ())
|
|
{
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
|
info_p->u8_arg = object_literal_flags | SCANNER_LITERAL_DESTRUCTURING_FOR;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_ASSIGN)
|
|
{
|
|
if (SCANNER_NEEDS_BINDING_LIST (binding_type))
|
|
{
|
|
scanner_pop_binding_list (scanner_context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
if ((stack_top == SCAN_STACK_ARRAY_LITERAL || stack_top == SCAN_STACK_OBJECT_LITERAL)
|
|
&& (binding_type == SCANNER_BINDING_NONE || binding_type == SCANNER_BINDING_ARROW_ARG)
|
|
&& context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_COMMA
|
|
&& context_p->token.type != LEXER_RIGHT_BRACE && context_p->token.type != LEXER_RIGHT_SQUARE)
|
|
{
|
|
object_literal_flags |= SCANNER_LITERAL_NO_DESTRUCTURING;
|
|
}
|
|
|
|
if (object_literal_flags != 0)
|
|
{
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_LITERAL_FLAGS;
|
|
info_p->u8_arg = object_literal_flags;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
scanner_location_info_t *location_info_p;
|
|
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
source_start.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
location_info_p->info.type = SCANNER_TYPE_INITIALIZER;
|
|
location_info_p->info.u8_arg = object_literal_flags;
|
|
scanner_get_location (&location_info_p->location, context_p);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (SCANNER_NEEDS_BINDING_LIST (binding_type))
|
|
{
|
|
scanner_binding_item_t *item_p = scanner_context_p->active_binding_list_p->items_p;
|
|
|
|
while (item_p != NULL)
|
|
{
|
|
item_p->literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_USED;
|
|
item_p = item_p->next_p;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_LIST_INIT);
|
|
}
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
case SCAN_STACK_OBJECT_LITERAL:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
parser_stack_pop_uint8 (context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_ARRAY_LITERAL:
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_PROPERTY_ACCESSOR:
|
|
{
|
|
if (type != LEXER_RIGHT_SQUARE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
parser_stack_pop_uint8 (context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_COMPUTED_PROPERTY:
|
|
{
|
|
if (type != LEXER_RIGHT_SQUARE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
|
|
|
if (stack_top == SCAN_STACK_FUNCTION_PROPERTY)
|
|
{
|
|
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR || stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
|
|
{
|
|
JERRY_ASSERT (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME);
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
scanner_push_class_field_initializer (context_p, scanner_context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
scanner_context_p->mode =
|
|
(context_p->token.type != LEXER_SEMICOLON ? SCAN_MODE_CLASS_BODY_NO_SCAN : SCAN_MODE_CLASS_BODY);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_push_literal_pool (context_p, scanner_context_p, SCANNER_LITERAL_POOL_FUNCTION);
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_COLON)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (scanner_context_p->binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_BINDING;
|
|
}
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_COMPUTED_GENERATOR:
|
|
case SCAN_STACK_COMPUTED_ASYNC:
|
|
case SCAN_STACK_COMPUTED_ASYNC_GENERATOR:
|
|
{
|
|
if (type != LEXER_RIGHT_SQUARE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_PROPERTY);
|
|
|
|
uint16_t status_flags = (uint16_t) (SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_GENERATOR
|
|
| SCANNER_FROM_COMPUTED_TO_LITERAL_POOL (stack_top));
|
|
|
|
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_TEMPLATE_STRING:
|
|
case SCAN_STACK_TAGGED_TEMPLATE_LITERAL:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
context_p->source_p--;
|
|
context_p->column--;
|
|
lexer_parse_string (context_p, LEXER_STRING_NO_OPTS);
|
|
|
|
if (context_p->source_p[-1] != LIT_CHAR_GRAVE_ACCENT)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
}
|
|
else
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
}
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_ARROW_ARGUMENTS:
|
|
{
|
|
if (type != LEXER_RIGHT_PAREN)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_check_arrow (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_ARROW_EXPRESSION:
|
|
{
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
parser_stack_pop_uint8 (context_p);
|
|
lexer_update_await_yield (context_p, context_p->status_flags);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_CLASS_EXTENDS:
|
|
{
|
|
if (type != LEXER_LEFT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_CLASS_FIELD_INITIALIZER:
|
|
{
|
|
scanner_source_start_t source_start;
|
|
const uint8_t *source_p = NULL;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN;
|
|
|
|
switch (type)
|
|
{
|
|
case LEXER_SEMICOLON:
|
|
{
|
|
source_p = context_p->source_p - 1;
|
|
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
|
break;
|
|
}
|
|
case LEXER_RIGHT_BRACE:
|
|
{
|
|
source_p = context_p->source_p - 1;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (type == LEXER_LEFT_SQUARE)
|
|
{
|
|
source_p = context_p->source_p - 1;
|
|
break;
|
|
}
|
|
|
|
if (type == LEXER_LITERAL)
|
|
{
|
|
if (context_p->token.lit_location.type == LEXER_IDENT_LITERAL
|
|
|| context_p->token.lit_location.type == LEXER_NUMBER_LITERAL)
|
|
{
|
|
source_p = context_p->token.lit_location.char_p;
|
|
}
|
|
else if (context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
|
{
|
|
source_p = context_p->token.lit_location.char_p - 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (type == context_p->token.keyword_type && type != LEXER_EOS)
|
|
{
|
|
/* Convert keyword to literal. */
|
|
source_p = context_p->token.lit_location.char_p;
|
|
context_p->token.type = LEXER_LITERAL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (JERRY_UNLIKELY (source_p == NULL))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_location_info_t *location_info_p;
|
|
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
source_start.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
location_info_p->info.type = SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END;
|
|
location_info_p->location.source_p = source_p;
|
|
location_info_p->location.line = context_p->token.line;
|
|
location_info_p->location.column = context_p->token.column;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_FUNCTION_PARAMETERS:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (type != LEXER_RIGHT_PAREN && (type != LEXER_EOS || context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION))
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
default:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
}
|
|
|
|
scanner_raise_error (context_p);
|
|
return SCAN_NEXT_TOKEN;
|
|
} /* scanner_scan_primary_expression_end */
|
|
|
|
/**
|
|
* Scan statements.
|
|
*
|
|
* @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
|
|
*/
|
|
static scan_return_types_t
|
|
scanner_scan_statement (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p, /**< scanner context */
|
|
lexer_token_type_t type, /**< current token type */
|
|
scan_stack_modes_t stack_top) /**< current stack top */
|
|
{
|
|
switch (type)
|
|
{
|
|
case LEXER_SEMICOLON:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_LEFT_BRACE:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_DO:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_DO_STATEMENT);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_TRY:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_TRY_STATEMENT);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_DEBUGGER:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_IF:
|
|
case LEXER_KEYW_WITH:
|
|
case LEXER_KEYW_SWITCH:
|
|
{
|
|
lexer_next_token (context_p);
|
|
if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
uint8_t mode = SCAN_STACK_STATEMENT_WITH_EXPR;
|
|
|
|
if (type == LEXER_KEYW_IF)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_IF_STATEMENT);
|
|
}
|
|
else if (type == LEXER_KEYW_WITH)
|
|
{
|
|
mode = SCAN_STACK_WITH_EXPRESSION;
|
|
}
|
|
else if (type == LEXER_KEYW_SWITCH)
|
|
{
|
|
mode = SCAN_STACK_SWITCH_EXPRESSION;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
parser_stack_push_uint8 (context_p, mode);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_WHILE:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
scanner_source_start_t source_start;
|
|
source_start.source_p = context_p->source_p;
|
|
|
|
parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_WHILE_EXPRESSION);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_FOR:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_KEYW_AWAIT)
|
|
{
|
|
lexer_next_token (context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_for_statement_t for_statement;
|
|
for_statement.u.source_p = context_p->source_p;
|
|
uint8_t stack_mode = SCAN_STACK_FOR_START;
|
|
scan_return_types_t return_type = SCAN_KEEP_TOKEN;
|
|
|
|
lexer_next_token (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
#if JERRY_ESNEXT
|
|
const uint8_t *source_p = context_p->source_p;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
switch (context_p->token.type)
|
|
{
|
|
case LEXER_SEMICOLON:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
break;
|
|
}
|
|
case LEXER_KEYW_VAR:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
stack_mode = SCAN_STACK_FOR_VAR_START;
|
|
return_type = SCAN_NEXT_TOKEN;
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_LEFT_BRACE:
|
|
case LEXER_LEFT_SQUARE:
|
|
{
|
|
stack_mode = SCAN_STACK_FOR_START_PATTERN;
|
|
break;
|
|
}
|
|
case LEXER_LITERAL:
|
|
{
|
|
if (!lexer_token_is_let (context_p))
|
|
{
|
|
break;
|
|
}
|
|
|
|
parser_line_counter_t line = context_p->line;
|
|
parser_line_counter_t column = context_p->column;
|
|
|
|
if (lexer_check_arrow (context_p))
|
|
{
|
|
context_p->source_p = source_p;
|
|
context_p->line = line;
|
|
context_p->column = column;
|
|
context_p->token.flags &= (uint8_t) ~LEXER_NO_SKIP_SPACES;
|
|
break;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
|
|
if (type != LEXER_LEFT_SQUARE && type != LEXER_LEFT_BRACE
|
|
&& (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL))
|
|
{
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_LET_EXPRESSION;
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
/* FALLTHRU */
|
|
}
|
|
case LEXER_KEYW_LET:
|
|
case LEXER_KEYW_CONST:
|
|
{
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = source_p;
|
|
|
|
if (scanner_context_p->mode == SCAN_MODE_PRIMARY_EXPRESSION)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
return_type = SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
stack_mode =
|
|
((context_p->token.type == LEXER_KEYW_CONST) ? SCAN_STACK_FOR_CONST_START : SCAN_STACK_FOR_LET_START);
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
}
|
|
|
|
parser_stack_push (context_p, &for_statement, sizeof (scanner_for_statement_t));
|
|
parser_stack_push_uint8 (context_p, stack_mode);
|
|
return return_type;
|
|
}
|
|
case LEXER_KEYW_VAR:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_VAR);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_KEYW_LET:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_CONST:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_CONST);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case LEXER_KEYW_THROW:
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_RETURN:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type != LEXER_SEMICOLON
|
|
&& context_p->token.type != LEXER_EOS && context_p->token.type != LEXER_RIGHT_BRACE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_KEYW_BREAK:
|
|
case LEXER_KEYW_CONTINUE:
|
|
{
|
|
lexer_next_token (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
|
|
if (!(context_p->token.flags & LEXER_WAS_NEWLINE) && context_p->token.type == LEXER_LITERAL
|
|
&& context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case LEXER_KEYW_CASE:
|
|
case LEXER_KEYW_DEFAULT:
|
|
{
|
|
if (stack_top != SCAN_STACK_SWITCH_BLOCK)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_case_info_t *case_info_p;
|
|
case_info_p = (scanner_case_info_t *) scanner_malloc (context_p, sizeof (scanner_case_info_t));
|
|
|
|
*(scanner_context_p->active_switch_statement.last_case_p) = case_info_p;
|
|
scanner_context_p->active_switch_statement.last_case_p = &case_info_p->next_p;
|
|
|
|
case_info_p->next_p = NULL;
|
|
scanner_get_location (&case_info_p->location, context_p);
|
|
|
|
if (type == LEXER_KEYW_DEFAULT)
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_COLON)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
scanner_source_start_t source_start;
|
|
source_start.source_p = context_p->source_p;
|
|
|
|
parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_CASE_STATEMENT);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_FUNCTION:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_FUNCTION_STATEMENT;
|
|
|
|
if (scanner_context_p->async_source_p != NULL)
|
|
{
|
|
scanner_context_p->status_flags |= SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
|
|
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
lexer_next_token (context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL);
|
|
|
|
if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL)
|
|
&& (literal_p->type & mask) != (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
|
|
&& (literal_p->type & mask) != SCANNER_LITERAL_IS_LOCAL_FUNC)
|
|
{
|
|
scanner_raise_redeclaration_error (context_p);
|
|
}
|
|
|
|
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
|
|
|
if (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION)
|
|
&& (literal_p->type & (SCANNER_LITERAL_IS_VAR)))
|
|
{
|
|
scanner_raise_redeclaration_error (context_p);
|
|
}
|
|
|
|
literal_p->type |= SCANNER_LITERAL_IS_LOCAL_FUNC;
|
|
|
|
scanner_context_p->status_flags &= (uint16_t) ~SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION;
|
|
#else /* !JERRY_ESNEXT */
|
|
literal_p->type |= SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC;
|
|
|
|
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_push_literal_pool (context_p, scanner_context_p, status_flags);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_STATEMENT);
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case LEXER_KEYW_CLASS:
|
|
{
|
|
lexer_lit_location_t *literal_p;
|
|
literal_p = scanner_push_class_declaration (context_p, scanner_context_p, SCAN_STACK_CLASS_STATEMENT);
|
|
|
|
if (literal_p == NULL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_detect_invalid_let (context_p, literal_p);
|
|
literal_p->type |= SCANNER_LITERAL_IS_LET;
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
}
|
|
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
|
scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
#if JERRY_MODULE_SYSTEM
|
|
case LEXER_KEYW_IMPORT:
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_DOT)
|
|
{
|
|
scanner_check_import_meta (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (stack_top != SCAN_STACK_SCRIPT)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
|
|
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
|
{
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
bool parse_imports = true;
|
|
|
|
if (context_p->token.type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
|
|
|
|
scanner_detect_invalid_let (context_p, literal_p);
|
|
literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_COMMA)
|
|
{
|
|
lexer_next_token (context_p);
|
|
}
|
|
else
|
|
{
|
|
parse_imports = false;
|
|
}
|
|
}
|
|
|
|
if (parse_imports)
|
|
{
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
lexer_next_token (context_p);
|
|
if (!lexer_token_is_identifier (context_p, "as", 2))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
|
|
|
|
scanner_detect_invalid_let (context_p, literal_p);
|
|
literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
else if (context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
while (context_p->token.type != LEXER_RIGHT_BRACE)
|
|
{
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
const uint8_t *source_p = context_p->source_p;
|
|
|
|
if (lexer_check_next_character (context_p, LIT_CHAR_LOWERCASE_A))
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (!lexer_token_is_identifier (context_p, "as", 2))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
source_p = context_p->source_p;
|
|
}
|
|
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p);
|
|
|
|
if (literal_p->type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_LOCAL))
|
|
{
|
|
context_p->source_p = source_p;
|
|
scanner_raise_redeclaration_error (context_p);
|
|
}
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
|
|
{
|
|
literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
|
|
}
|
|
|
|
literal_p->type |= SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_NO_REG;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_BRACE)
|
|
{
|
|
if (context_p->token.type != LEXER_COMMA)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
else
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
}
|
|
|
|
if (!lexer_token_is_identifier (context_p, "from", 4))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type != LEXER_STRING_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case LEXER_KEYW_EXPORT:
|
|
{
|
|
if (stack_top != SCAN_STACK_SCRIPT)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_KEYW_DEFAULT)
|
|
{
|
|
lexer_next_token (context_p);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_EXPORT_DEFAULT);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_END;
|
|
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (lexer_token_is_identifier (context_p, "as", 2))
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
if (!lexer_token_is_identifier (context_p, "from", 4))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
scanner_source_start_t source_start;
|
|
source_start.source_p = context_p->source_p;
|
|
|
|
if (context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
while (context_p->token.type != LEXER_RIGHT_BRACE)
|
|
{
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (lexer_token_is_identifier (context_p, "as", 2))
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_BRACE)
|
|
{
|
|
if (context_p->token.type != LEXER_COMMA)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (!lexer_token_is_identifier (context_p, "from", 4))
|
|
{
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_start.source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_EXPORT_MODULE_SPECIFIER;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL && context_p->token.lit_location.type == LEXER_STRING_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
switch (context_p->token.type)
|
|
{
|
|
case LEXER_KEYW_CLASS:
|
|
case LEXER_KEYW_LET:
|
|
case LEXER_KEYW_CONST:
|
|
case LEXER_KEYW_VAR:
|
|
{
|
|
scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_IN_EXPORT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL)
|
|
{
|
|
if (JERRY_UNLIKELY (lexer_check_next_character (context_p, LIT_CHAR_COLON)))
|
|
{
|
|
lexer_consume_next_character (context_p);
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
JERRY_ASSERT (context_p->token.flags & LEXER_NO_SKIP_SPACES);
|
|
|
|
#if JERRY_ESNEXT
|
|
/* The colon needs to be checked first because the parser also checks
|
|
* it first, and this check skips the spaces which affects source_p. */
|
|
if (JERRY_UNLIKELY (lexer_check_arrow (context_p)))
|
|
{
|
|
scanner_scan_simple_arrow (context_p, scanner_context_p, context_p->source_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (JERRY_UNLIKELY (lexer_token_is_let (context_p)))
|
|
{
|
|
lexer_lit_location_t let_literal = context_p->token.lit_location;
|
|
const uint8_t *source_p = context_p->source_p;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
|
|
if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE
|
|
|| (type == LEXER_LITERAL && context_p->token.lit_location.type == LEXER_IDENT_LITERAL))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_VAR_STATEMENT;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_LET);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
scanner_info_t *info_p = scanner_insert_info (context_p, source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_LET_EXPRESSION;
|
|
|
|
lexer_lit_location_t *lit_location_p =
|
|
scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &let_literal);
|
|
lit_location_p->type |= SCANNER_LITERAL_IS_USED;
|
|
|
|
if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
lit_location_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (JERRY_UNLIKELY (lexer_token_is_async (context_p)))
|
|
{
|
|
scanner_context_p->async_source_p = context_p->source_p;
|
|
|
|
if (scanner_check_async_function (context_p, scanner_context_p))
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
}
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_add_reference (context_p, scanner_context_p);
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
return SCAN_KEEP_TOKEN;
|
|
} /* scanner_scan_statement */
|
|
|
|
/**
|
|
* Scan statement terminator.
|
|
*
|
|
* @return SCAN_NEXT_TOKEN to read the next token, or SCAN_KEEP_TOKEN to do nothing
|
|
*/
|
|
static scan_return_types_t
|
|
scanner_scan_statement_end (parser_context_t *context_p, /**< context */
|
|
scanner_context_t *scanner_context_p, /**< scanner context */
|
|
lexer_token_type_t type) /**< current token type */
|
|
{
|
|
bool terminator_found = false;
|
|
|
|
if (type == LEXER_SEMICOLON)
|
|
{
|
|
lexer_next_token (context_p);
|
|
terminator_found = true;
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
|
|
switch (context_p->stack_top_uint8)
|
|
{
|
|
case SCAN_STACK_SCRIPT:
|
|
case SCAN_STACK_SCRIPT_FUNCTION:
|
|
{
|
|
if (type == LEXER_EOS)
|
|
{
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
break;
|
|
}
|
|
case SCAN_STACK_BLOCK_STATEMENT:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_CLASS_STATEMENT:
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_STACK_FUNCTION_STATEMENT:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 != SCAN_STACK_CLASS_STATEMENT)
|
|
{
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_STATEMENT)
|
|
{
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
terminator_found = true;
|
|
parser_stack_pop_uint8 (context_p);
|
|
#if JERRY_MODULE_SYSTEM
|
|
scanner_context_p->active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
lexer_next_token (context_p);
|
|
continue;
|
|
}
|
|
case SCAN_STACK_FUNCTION_EXPRESSION:
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_FUNCTION_ARROW:
|
|
#endif /* JERRY_ESNEXT */
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_FUNCTION_ARROW)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT)
|
|
{
|
|
terminator_found = true;
|
|
parser_stack_pop_uint8 (context_p);
|
|
lexer_next_token (context_p);
|
|
continue;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_FUNCTION_PROPERTY:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
bool has_super_reference =
|
|
(scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_HAS_SUPER_REFERENCE) != 0;
|
|
#endif /* JERRY_ESNEXT */
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_CLASS_BODY;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (has_super_reference && context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL)
|
|
{
|
|
*parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_SUPER;
|
|
}
|
|
#else /* JERRY_ESNEXT */
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_OBJECT_LITERAL);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_COMMA)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_SWITCH_BLOCK:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_switch_statement_t switch_statement;
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &switch_statement, sizeof (scanner_switch_statement_t));
|
|
|
|
scanner_context_p->active_switch_statement = switch_statement;
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
terminator_found = true;
|
|
lexer_next_token (context_p);
|
|
continue;
|
|
}
|
|
case SCAN_STACK_IF_STATEMENT:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (type == LEXER_KEYW_ELSE && (terminator_found || (context_p->token.flags & LEXER_WAS_NEWLINE)))
|
|
{
|
|
#if JERRY_ESNEXT
|
|
scanner_check_function_after_if (context_p, scanner_context_p);
|
|
return SCAN_KEEP_TOKEN;
|
|
#else /* !JERRY_ESNEXT */
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_NEXT_TOKEN;
|
|
#endif /* JERRY_ESNEXT */
|
|
}
|
|
continue;
|
|
}
|
|
case SCAN_STACK_WITH_STATEMENT:
|
|
{
|
|
scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
|
|
|
|
JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH);
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (context_p->stack_top_uint8 == 0)
|
|
{
|
|
literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_WITH;
|
|
}
|
|
|
|
parser_stack_pop_uint8 (context_p);
|
|
continue;
|
|
}
|
|
case SCAN_STACK_DO_STATEMENT:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
if (type != LEXER_KEYW_WHILE || (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE)))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_DO_EXPRESSION);
|
|
scanner_context_p->mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
case SCAN_STACK_DO_EXPRESSION:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
terminator_found = true;
|
|
continue;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_STACK_CLASS_STATIC_BLOCK:
|
|
{
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
scanner_source_start_t start_range;
|
|
parser_stack_pop_uint8 (context_p);
|
|
parser_stack_pop (context_p, &start_range, sizeof (scanner_source_start_t));
|
|
|
|
scanner_context_p->mode = SCAN_MODE_CLASS_BODY_NO_SCAN;
|
|
|
|
scanner_location_info_t *location_info_p;
|
|
location_info_p = (scanner_location_info_t *) scanner_insert_info (context_p,
|
|
start_range.source_p,
|
|
sizeof (scanner_location_info_t));
|
|
|
|
location_info_p->info.type = SCANNER_TYPE_CLASS_STATIC_BLOCK_END;
|
|
location_info_p->location.source_p = context_p->source_p;
|
|
location_info_p->location.line = context_p->token.line;
|
|
location_info_p->location.column = context_p->token.column;
|
|
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_CHECK_KEYWORDS | LEXER_PARSE_NO_STRICT_IDENT_ERROR);
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
case SCAN_STACK_PRIVATE_BLOCK_EARLY:
|
|
{
|
|
parser_list_iterator_t literal_iterator;
|
|
lexer_lit_location_t *literal_p;
|
|
|
|
parser_list_iterator_init (&scanner_context_p->active_literal_pool_p->literal_pool, &literal_iterator);
|
|
|
|
while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
|
|
{
|
|
if ((literal_p->type & (SCANNER_LITERAL_IS_LET | SCANNER_LITERAL_IS_CONST))
|
|
&& (literal_p->type & SCANNER_LITERAL_IS_USED))
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
}
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_STACK_PRIVATE_BLOCK:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
continue;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
#if JERRY_MODULE_SYSTEM
|
|
case SCAN_STACK_EXPORT_DEFAULT:
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
lexer_lit_location_t *location_p =
|
|
scanner_add_custom_literal (context_p, scanner_context_p->active_literal_pool_p, &lexer_default_literal);
|
|
location_p->type |= SCANNER_LITERAL_IS_VAR;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
default:
|
|
{
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_TRY_STATEMENT
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_CATCH_STATEMENT);
|
|
|
|
if (type != LEXER_RIGHT_BRACE)
|
|
{
|
|
break;
|
|
}
|
|
|
|
uint8_t stack_top = context_p->stack_top_uint8;
|
|
parser_stack_pop_uint8 (context_p);
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
#else /* !JERRY_ESNEXT */
|
|
if (stack_top == SCAN_STACK_CATCH_STATEMENT)
|
|
{
|
|
scanner_pop_literal_pool (context_p, scanner_context_p);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
/* A finally statement is optional after a try or catch statement. */
|
|
if (context_p->token.type == LEXER_KEYW_FINALLY)
|
|
{
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BLOCK_STATEMENT);
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
if (stack_top == SCAN_STACK_CATCH_STATEMENT)
|
|
{
|
|
terminator_found = true;
|
|
continue;
|
|
}
|
|
|
|
/* A catch statement must be present after a try statement unless a finally is provided. */
|
|
if (context_p->token.type != LEXER_KEYW_CATCH)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
scanner_literal_pool_t *literal_pool_p;
|
|
literal_pool_p = scanner_push_literal_pool (context_p, scanner_context_p, 0);
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_CATCH_STATEMENT);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_push_destructuring_pattern (context_p, scanner_context_p, SCANNER_BINDING_CATCH, false);
|
|
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_BINDING;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, 0);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context_p->mode = SCAN_MODE_PROPERTY_NAME;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_lit_location_t *lit_location_p = scanner_add_literal (context_p, scanner_context_p);
|
|
lit_location_p->type |= SCANNER_LITERAL_IS_LOCAL;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
return SCAN_NEXT_TOKEN;
|
|
}
|
|
}
|
|
|
|
if (!terminator_found && !(context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context_p->mode = SCAN_MODE_STATEMENT;
|
|
return SCAN_KEEP_TOKEN;
|
|
}
|
|
} /* scanner_scan_statement_end */
|
|
|
|
/**
|
|
* Scan the whole source code.
|
|
*/
|
|
void JERRY_ATTR_NOINLINE
|
|
scanner_scan_all (parser_context_t *context_p) /**< context */
|
|
{
|
|
scanner_context_t scanner_context;
|
|
|
|
#if JERRY_PARSER_DUMP_BYTE_CODE
|
|
if (context_p->is_show_opcodes)
|
|
{
|
|
JERRY_DEBUG_MSG ("\n--- Scanning start ---\n\n");
|
|
}
|
|
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */
|
|
|
|
scanner_context.context_status_flags = context_p->status_flags;
|
|
scanner_context.status_flags = SCANNER_CONTEXT_NO_FLAGS;
|
|
#if JERRY_DEBUGGER
|
|
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
|
{
|
|
scanner_context.status_flags |= SCANNER_CONTEXT_DEBUGGER_ENABLED;
|
|
}
|
|
#endif /* JERRY_DEBUGGER */
|
|
#if JERRY_ESNEXT
|
|
scanner_context.binding_type = SCANNER_BINDING_NONE;
|
|
scanner_context.active_binding_list_p = NULL;
|
|
#endif /* JERRY_ESNEXT */
|
|
scanner_context.active_literal_pool_p = NULL;
|
|
scanner_context.active_switch_statement.last_case_p = NULL;
|
|
scanner_context.end_arguments_p = NULL;
|
|
#if JERRY_ESNEXT
|
|
scanner_context.async_source_p = NULL;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
/* This assignment must be here because of Apple compilers. */
|
|
context_p->u.scanner_context_p = &scanner_context;
|
|
#if JERRY_ESNEXT
|
|
context_p->global_status_flags |= ECMA_PARSE_INTERNAL_PRE_SCANNING;
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_init (context_p);
|
|
|
|
PARSER_TRY (context_p->try_buffer)
|
|
{
|
|
if (context_p->arguments_start_p == NULL)
|
|
{
|
|
context_p->source_p = context_p->source_start_p;
|
|
context_p->source_end_p = context_p->source_start_p + context_p->source_size;
|
|
|
|
uint16_t status_flags =
|
|
(SCANNER_LITERAL_POOL_FUNCTION | SCANNER_LITERAL_POOL_NO_ARGUMENTS | SCANNER_LITERAL_POOL_CAN_EVAL);
|
|
|
|
if (context_p->status_flags & PARSER_IS_STRICT)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
|
|
}
|
|
|
|
scanner_literal_pool_t *literal_pool_p = scanner_push_literal_pool (context_p, &scanner_context, status_flags);
|
|
literal_pool_p->source_p = context_p->source_start_p;
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT);
|
|
|
|
lexer_next_token (context_p);
|
|
scanner_check_directives (context_p, &scanner_context);
|
|
}
|
|
else
|
|
{
|
|
context_p->source_p = context_p->arguments_start_p;
|
|
context_p->source_end_p = context_p->arguments_start_p + context_p->arguments_size;
|
|
|
|
uint16_t status_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
|
|
|
if (context_p->status_flags & PARSER_IS_STRICT)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_IS_STRICT;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
|
|
{
|
|
status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
scanner_push_literal_pool (context_p, &scanner_context, status_flags);
|
|
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_SCRIPT_FUNCTION);
|
|
|
|
/* Faking the first token. */
|
|
context_p->token.type = LEXER_LEFT_PAREN;
|
|
}
|
|
|
|
while (true)
|
|
{
|
|
lexer_token_type_t type = (lexer_token_type_t) context_p->token.type;
|
|
scan_stack_modes_t stack_top = (scan_stack_modes_t) context_p->stack_top_uint8;
|
|
|
|
switch (scanner_context.mode)
|
|
{
|
|
case SCAN_MODE_PRIMARY_EXPRESSION:
|
|
{
|
|
if (type == LEXER_ADD || type == LEXER_SUBTRACT || LEXER_IS_UNARY_OP_TOKEN (type))
|
|
{
|
|
break;
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_PRIMARY_EXPRESSION_AFTER_NEW:
|
|
{
|
|
if (scanner_scan_primary_expression (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_MODE_CLASS_DECLARATION:
|
|
{
|
|
if (context_p->token.type == LEXER_KEYW_EXTENDS)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_EXTENDS);
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
else if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_CLASS_BODY;
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_CLASS_BODY:
|
|
{
|
|
lexer_skip_empty_statements (context_p);
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_CLASS_BODY_NO_SCAN:
|
|
{
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR
|
|
|| stack_top == SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
|
|
JERRY_ASSERT (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CLASS_NAME);
|
|
|
|
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
scanner_class_info_t *private_members_p;
|
|
parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *));
|
|
|
|
private_members_p->info.u8_arg |= SCANNER_SUCCESSFUL_CLASS_SCAN;
|
|
|
|
scanner_pop_literal_pool (context_p, &scanner_context);
|
|
|
|
JERRY_ASSERT (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT
|
|
|| context_p->stack_top_uint8 == SCAN_STACK_CLASS_EXPRESSION);
|
|
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_CLASS_STATEMENT)
|
|
{
|
|
/* The token is kept to disallow consuming a semicolon after it. */
|
|
scanner_context.mode = SCAN_MODE_STATEMENT_END;
|
|
continue;
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
parser_stack_pop_uint8 (context_p);
|
|
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (context_p->stack_top_uint8 == SCAN_STACK_EXPORT_DEFAULT)
|
|
{
|
|
/* The token is kept to disallow consuming a semicolon after it. */
|
|
parser_stack_change_last_uint8 (context_p, SCAN_STACK_CLASS_STATEMENT);
|
|
scanner_context.mode = SCAN_MODE_STATEMENT_END;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
break;
|
|
}
|
|
|
|
bool is_private = false;
|
|
scanner_private_field_flags_t private_field_flags = SCANNER_PRIVATE_FIELD_PROPERTY;
|
|
|
|
if (context_p->token.type == LEXER_HASHMARK)
|
|
{
|
|
is_private = true;
|
|
context_p->token.flags |= LEXER_NO_SKIP_SPACES;
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
bool identifier_found = false;
|
|
|
|
if (context_p->token.type == LEXER_LITERAL && LEXER_IS_IDENT_OR_STRING (context_p->token.lit_location.type)
|
|
&& lexer_compare_literal_to_string (context_p, "constructor", 11)
|
|
&& stack_top == SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR)
|
|
{
|
|
parser_stack_pop_uint8 (context_p);
|
|
scanner_class_info_t *private_members_p;
|
|
parser_stack_pop (context_p, &private_members_p, sizeof (scanner_class_info_t *));
|
|
private_members_p->info.u8_arg = SCANNER_CONSTRUCTOR_EXPLICIT;
|
|
parser_stack_push (context_p, &private_members_p, sizeof (scanner_class_info_t *));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_EXPLICIT_CLASS_CONSTRUCTOR);
|
|
}
|
|
else if (lexer_token_is_identifier (context_p, "static", 6))
|
|
{
|
|
scanner_source_start_t static_start;
|
|
static_start.source_p = context_p->source_p - 1;
|
|
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
identifier_found = true;
|
|
private_field_flags |= SCANNER_PRIVATE_FIELD_STATIC;
|
|
|
|
if (!is_private && context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
parser_stack_push (context_p, &static_start, sizeof (scanner_source_start_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_CLASS_STATIC_BLOCK);
|
|
|
|
scanner_literal_pool_t *literal_pool_p =
|
|
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
|
literal_pool_p->source_p = context_p->source_p - 1;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
scanner_context.mode = SCAN_MODE_STATEMENT_OR_TERMINATOR;
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
|
|
uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
|
|
|
private_field_flags |= lexer_token_is_identifier (context_p, "get", 3) ? SCANNER_PRIVATE_FIELD_GETTER : 0;
|
|
private_field_flags |= lexer_token_is_identifier (context_p, "set", 3) ? SCANNER_PRIVATE_FIELD_SETTER : 0;
|
|
|
|
if (private_field_flags & SCANNER_PRIVATE_FIELD_GETTER_SETTER)
|
|
{
|
|
private_field_flags &= ~(uint32_t) SCANNER_PRIVATE_FIELD_PROPERTY;
|
|
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
identifier_found = true;
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
if (is_private)
|
|
{
|
|
private_field_flags |= SCANNER_PRIVATE_FIELD_METHOD;
|
|
scanner_add_private_identifier (context_p, private_field_flags);
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
|
continue;
|
|
}
|
|
}
|
|
else if (lexer_token_is_identifier (context_p, "async", 5))
|
|
{
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
identifier_found = true;
|
|
|
|
if (!(context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
if (is_private)
|
|
{
|
|
private_field_flags |= SCANNER_PRIVATE_FIELD_METHOD;
|
|
scanner_add_private_identifier (context_p, private_field_flags);
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
|
continue;
|
|
}
|
|
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
}
|
|
}
|
|
else if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
if (is_private)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
|
{
|
|
if (is_private)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
if (literal_pool_flags != SCANNER_LITERAL_POOL_FUNCTION)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_HASHMARK)
|
|
{
|
|
if (is_private)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
is_private = true;
|
|
context_p->token.flags |= LEXER_NO_SKIP_SPACES;
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
if (is_private)
|
|
{
|
|
if (lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
|
|
{
|
|
private_field_flags |= SCANNER_PRIVATE_FIELD_METHOD;
|
|
}
|
|
|
|
scanner_add_private_identifier (context_p, private_field_flags);
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LITERAL)
|
|
{
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
identifier_found = true;
|
|
}
|
|
|
|
if (!identifier_found)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
|
{
|
|
context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
|
|
continue;
|
|
}
|
|
|
|
if (literal_pool_flags & SCANNER_LITERAL_POOL_GENERATOR)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
scanner_push_class_field_initializer (context_p, &scanner_context);
|
|
break;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_SEMICOLON)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_CLASS_BODY;
|
|
continue;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_BRACE && !(context_p->token.flags & LEXER_WAS_NEWLINE))
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_CLASS_BODY_NO_SCAN;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCAN_MODE_POST_PRIMARY_EXPRESSION:
|
|
{
|
|
if (scanner_scan_post_primary_expression (context_p, &scanner_context, type, stack_top))
|
|
{
|
|
break;
|
|
}
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_PRIMARY_EXPRESSION_END:
|
|
{
|
|
if (scanner_scan_primary_expression_end (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
case SCAN_MODE_STATEMENT_OR_TERMINATOR:
|
|
{
|
|
if (type == LEXER_RIGHT_BRACE || type == LEXER_EOS)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_STATEMENT_END;
|
|
continue;
|
|
}
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_STATEMENT:
|
|
{
|
|
if (scanner_scan_statement (context_p, &scanner_context, type, stack_top) != SCAN_NEXT_TOKEN)
|
|
{
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
case SCAN_MODE_STATEMENT_END:
|
|
{
|
|
if (scanner_scan_statement_end (context_p, &scanner_context, type) != SCAN_NEXT_TOKEN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_EOS)
|
|
{
|
|
goto scan_completed;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case SCAN_MODE_VAR_STATEMENT:
|
|
{
|
|
#if JERRY_ESNEXT
|
|
if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE)
|
|
{
|
|
uint8_t binding_type = SCANNER_BINDING_VAR;
|
|
|
|
if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START)
|
|
{
|
|
binding_type = SCANNER_BINDING_LET;
|
|
}
|
|
else if (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START)
|
|
{
|
|
binding_type = SCANNER_BINDING_CONST;
|
|
}
|
|
|
|
scanner_push_destructuring_pattern (context_p, &scanner_context, binding_type, false);
|
|
|
|
if (type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
scanner_context.mode = SCAN_MODE_BINDING;
|
|
break;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, 0);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (stack_top != SCAN_STACK_VAR && stack_top != SCAN_STACK_FOR_VAR_START)
|
|
{
|
|
scanner_detect_invalid_let (context_p, literal_p);
|
|
|
|
if (stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_FOR_LET_START)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_IS_LET;
|
|
}
|
|
else
|
|
{
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_CONST || stack_top == SCAN_STACK_FOR_CONST_START);
|
|
literal_p->type |= SCANNER_LITERAL_IS_CONST;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
}
|
|
else if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
scanner_binding_literal_t binding_literal;
|
|
binding_literal.literal_p = literal_p;
|
|
|
|
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
|
|
{
|
|
scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
|
|
literal_p->type |= SCANNER_LITERAL_IS_VAR;
|
|
|
|
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
literal_p->type |= SCANNER_LITERAL_IS_VAR;
|
|
|
|
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
#if JERRY_MODULE_SYSTEM
|
|
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
switch (context_p->token.type)
|
|
{
|
|
case LEXER_ASSIGN:
|
|
{
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
/* FALLTHRU */
|
|
}
|
|
case LEXER_COMMA:
|
|
{
|
|
lexer_next_token (context_p);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (SCANNER_IS_FOR_START (stack_top))
|
|
{
|
|
#if JERRY_MODULE_SYSTEM
|
|
JERRY_ASSERT (!(scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_EXPORT));
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
if (context_p->token.type != LEXER_SEMICOLON && context_p->token.type != LEXER_KEYW_IN
|
|
&& !SCANNER_IDENTIFIER_IS_OF ())
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
continue;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_VAR || stack_top == SCAN_STACK_LET || stack_top == SCAN_STACK_CONST);
|
|
#else /* !JERRY_ESNEXT */
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_VAR);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
#if JERRY_MODULE_SYSTEM
|
|
scanner_context.active_literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_IN_EXPORT;
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
|
|
scanner_context.mode = SCAN_MODE_STATEMENT_END;
|
|
parser_stack_pop_uint8 (context_p);
|
|
continue;
|
|
}
|
|
case SCAN_MODE_FUNCTION_ARGUMENTS:
|
|
{
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_SCRIPT_FUNCTION || stack_top == SCAN_STACK_FUNCTION_STATEMENT
|
|
|| stack_top == SCAN_STACK_FUNCTION_EXPRESSION || stack_top == SCAN_STACK_FUNCTION_PROPERTY);
|
|
|
|
scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p;
|
|
|
|
JERRY_ASSERT (literal_pool_p != NULL && (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION));
|
|
|
|
literal_pool_p->source_p = context_p->source_p;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (JERRY_UNLIKELY (scanner_context.async_source_p != NULL))
|
|
{
|
|
literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
literal_pool_p->source_p = scanner_context.async_source_p;
|
|
scanner_context.async_source_p = NULL;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (type != LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
/* FALLTHRU */
|
|
}
|
|
case SCAN_MODE_CONTINUE_FUNCTION_ARGUMENTS:
|
|
{
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
|
|
{
|
|
lexer_lit_location_t *argument_literal_p;
|
|
|
|
do
|
|
{
|
|
if (context_p->token.type == LEXER_THREE_DOTS)
|
|
{
|
|
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT;
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
|
|
{
|
|
argument_literal_p = NULL;
|
|
break;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
argument_literal_p = scanner_append_argument (context_p, &scanner_context);
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_COMMA)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
} while (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS);
|
|
|
|
if (argument_literal_p == NULL)
|
|
{
|
|
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT;
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
|
|
scanner_append_hole (context_p, &scanner_context);
|
|
scanner_push_destructuring_pattern (context_p, &scanner_context, SCANNER_BINDING_ARG, false);
|
|
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
scanner_context.mode = SCAN_MODE_BINDING;
|
|
break;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, 0);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
|
continue;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
scanner_context.active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_HAS_COMPLEX_ARGUMENT;
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PARAMETERS);
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (argument_literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
JERRY_ASSERT (argument_literal_p->type & SCANNER_LITERAL_EARLY_CREATE);
|
|
break;
|
|
}
|
|
|
|
scanner_binding_literal_t binding_literal;
|
|
binding_literal.literal_p = argument_literal_p;
|
|
|
|
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
|
break;
|
|
}
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN && context_p->token.type != LEXER_EOS)
|
|
{
|
|
while (true)
|
|
{
|
|
if (context_p->token.type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_append_argument (context_p, &scanner_context);
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_COMMA)
|
|
{
|
|
break;
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type == LEXER_EOS && stack_top == SCAN_STACK_SCRIPT_FUNCTION)
|
|
{
|
|
/* End of argument parsing. */
|
|
scanner_info_t *scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, sizeof (scanner_info_t));
|
|
scanner_info_p->next_p = context_p->next_scanner_info_p;
|
|
scanner_info_p->source_p = NULL;
|
|
scanner_info_p->type = SCANNER_TYPE_END_ARGUMENTS;
|
|
scanner_context.end_arguments_p = scanner_info_p;
|
|
|
|
context_p->next_scanner_info_p = scanner_info_p;
|
|
context_p->source_p = context_p->source_start_p;
|
|
context_p->source_end_p = context_p->source_start_p + context_p->source_size;
|
|
lexer_init_line_info (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_filter_arguments (context_p, &scanner_context);
|
|
#endif /* JERRY_ESNEXT */
|
|
lexer_next_token (context_p);
|
|
scanner_check_directives (context_p, &scanner_context);
|
|
continue;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_RIGHT_PAREN)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type != LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
scanner_filter_arguments (context_p, &scanner_context);
|
|
#endif /* JERRY_ESNEXT */
|
|
lexer_next_token (context_p);
|
|
scanner_check_directives (context_p, &scanner_context);
|
|
continue;
|
|
}
|
|
case SCAN_MODE_PROPERTY_NAME:
|
|
{
|
|
JERRY_ASSERT (stack_top == SCAN_STACK_OBJECT_LITERAL);
|
|
|
|
if (lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS))
|
|
{
|
|
lexer_check_property_modifier (context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_COMPUTED_PROPERTY);
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_THREE_DOTS)
|
|
{
|
|
*parser_stack_get_prev_uint8 (context_p) |= SCANNER_LITERAL_OBJECT_HAS_REST;
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
if (scanner_context.binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_BINDING;
|
|
}
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type == LEXER_RIGHT_BRACE)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
continue;
|
|
}
|
|
|
|
if (context_p->token.type == LEXER_PROPERTY_GETTER
|
|
#if JERRY_ESNEXT
|
|
|| context_p->token.type == LEXER_KEYW_ASYNC || context_p->token.type == LEXER_MULTIPLY
|
|
#endif /* JERRY_ESNEXT */
|
|
|| context_p->token.type == LEXER_PROPERTY_SETTER)
|
|
{
|
|
uint16_t literal_pool_flags = SCANNER_LITERAL_POOL_FUNCTION;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_MULTIPLY)
|
|
{
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
else if (context_p->token.type == LEXER_KEYW_ASYNC)
|
|
{
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_ASYNC;
|
|
|
|
if (lexer_consume_generator (context_p))
|
|
{
|
|
literal_pool_flags |= SCANNER_LITERAL_POOL_GENERATOR;
|
|
}
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
lexer_scan_identifier (context_p, LEXER_PARSE_NO_OPTS);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCANNER_FROM_LITERAL_POOL_TO_COMPUTED (literal_pool_flags));
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_push_literal_pool (context_p, &scanner_context, literal_pool_flags);
|
|
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
break;
|
|
}
|
|
|
|
if (context_p->token.type != LEXER_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
parser_line_counter_t start_line = context_p->token.line;
|
|
parser_line_counter_t start_column = context_p->token.column;
|
|
bool is_ident = (context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
#if JERRY_ESNEXT
|
|
if (context_p->token.type == LEXER_LEFT_PAREN)
|
|
{
|
|
scanner_push_literal_pool (context_p, &scanner_context, SCANNER_LITERAL_POOL_FUNCTION);
|
|
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_FUNCTION_PROPERTY);
|
|
scanner_context.mode = SCAN_MODE_FUNCTION_ARGUMENTS;
|
|
continue;
|
|
}
|
|
|
|
if (is_ident
|
|
&& (context_p->token.type == LEXER_COMMA || context_p->token.type == LEXER_RIGHT_BRACE
|
|
|| context_p->token.type == LEXER_ASSIGN))
|
|
{
|
|
context_p->source_p = context_p->token.lit_location.char_p;
|
|
context_p->line = start_line;
|
|
context_p->column = start_column;
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
JERRY_ASSERT (context_p->token.type != LEXER_LITERAL
|
|
|| context_p->token.lit_location.type == LEXER_IDENT_LITERAL);
|
|
|
|
if (context_p->token.type != LEXER_LITERAL)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
if (scanner_context.binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_BINDING;
|
|
continue;
|
|
}
|
|
|
|
scanner_add_reference (context_p, &scanner_context);
|
|
|
|
lexer_next_token (context_p);
|
|
|
|
if (context_p->token.type == LEXER_ASSIGN)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION_END;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (context_p->token.type != LEXER_COLON)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
|
|
#if JERRY_ESNEXT
|
|
if (scanner_context.binding_type != SCANNER_BINDING_NONE)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_BINDING;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCAN_MODE_BINDING:
|
|
{
|
|
JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR
|
|
|| scanner_context.binding_type == SCANNER_BINDING_LET
|
|
|| scanner_context.binding_type == SCANNER_BINDING_CATCH
|
|
|| scanner_context.binding_type == SCANNER_BINDING_CONST
|
|
|| scanner_context.binding_type == SCANNER_BINDING_ARG
|
|
|| scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG);
|
|
|
|
if (type == LEXER_THREE_DOTS)
|
|
{
|
|
lexer_next_token (context_p);
|
|
type = (lexer_token_type_t) context_p->token.type;
|
|
}
|
|
|
|
if (type == LEXER_LEFT_SQUARE || type == LEXER_LEFT_BRACE)
|
|
{
|
|
scanner_push_destructuring_pattern (context_p, &scanner_context, scanner_context.binding_type, true);
|
|
|
|
if (type == LEXER_LEFT_SQUARE)
|
|
{
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_ARRAY_LITERAL);
|
|
break;
|
|
}
|
|
|
|
parser_stack_push_uint8 (context_p, 0);
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_OBJECT_LITERAL);
|
|
scanner_context.mode = SCAN_MODE_PROPERTY_NAME;
|
|
continue;
|
|
}
|
|
|
|
if (type != LEXER_LITERAL || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
|
|
{
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
continue;
|
|
}
|
|
|
|
lexer_lit_location_t *literal_p = scanner_add_literal (context_p, &scanner_context);
|
|
|
|
scanner_context.mode = SCAN_MODE_POST_PRIMARY_EXPRESSION;
|
|
|
|
if (scanner_context.binding_type == SCANNER_BINDING_VAR)
|
|
{
|
|
if (!(literal_p->type & SCANNER_LITERAL_IS_VAR))
|
|
{
|
|
scanner_detect_invalid_var (context_p, &scanner_context, literal_p);
|
|
literal_p->type |= SCANNER_LITERAL_IS_VAR;
|
|
|
|
if (scanner_context.active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_NO_REG;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scanner_detect_invalid_let (context_p, literal_p);
|
|
|
|
if (scanner_context.binding_type <= SCANNER_BINDING_CATCH)
|
|
{
|
|
JERRY_ASSERT ((scanner_context.binding_type == SCANNER_BINDING_LET)
|
|
|| (scanner_context.binding_type == SCANNER_BINDING_CATCH));
|
|
|
|
literal_p->type |= SCANNER_LITERAL_IS_LET;
|
|
}
|
|
else
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_IS_CONST;
|
|
|
|
if (scanner_context.binding_type == SCANNER_BINDING_ARG)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_IS_ARG;
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (literal_p->type & SCANNER_LITERAL_IS_USED)
|
|
{
|
|
literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
scanner_binding_item_t *binding_item_p;
|
|
binding_item_p = (scanner_binding_item_t *) scanner_malloc (context_p, sizeof (scanner_binding_item_t));
|
|
|
|
binding_item_p->next_p = scanner_context.active_binding_list_p->items_p;
|
|
binding_item_p->literal_p = literal_p;
|
|
|
|
scanner_context.active_binding_list_p->items_p = binding_item_p;
|
|
|
|
lexer_next_token (context_p);
|
|
if (context_p->token.type != LEXER_ASSIGN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
scanner_binding_literal_t binding_literal;
|
|
binding_literal.literal_p = literal_p;
|
|
|
|
parser_stack_push (context_p, &binding_literal, sizeof (scanner_binding_literal_t));
|
|
parser_stack_push_uint8 (context_p, SCAN_STACK_BINDING_INIT);
|
|
|
|
scanner_context.mode = SCAN_MODE_PRIMARY_EXPRESSION;
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
}
|
|
|
|
lexer_next_token (context_p);
|
|
}
|
|
|
|
scan_completed:
|
|
if (context_p->stack_top_uint8 != SCAN_STACK_SCRIPT && context_p->stack_top_uint8 != SCAN_STACK_SCRIPT_FUNCTION)
|
|
{
|
|
scanner_raise_error (context_p);
|
|
}
|
|
|
|
scanner_pop_literal_pool (context_p, &scanner_context);
|
|
|
|
#if JERRY_ESNEXT
|
|
JERRY_ASSERT (scanner_context.active_binding_list_p == NULL);
|
|
#endif /* JERRY_ESNEXT */
|
|
JERRY_ASSERT (scanner_context.active_literal_pool_p == NULL);
|
|
|
|
#ifndef JERRY_NDEBUG
|
|
scanner_context.context_status_flags |= PARSER_SCANNING_SUCCESSFUL;
|
|
#endif /* !JERRY_NDEBUG */
|
|
}
|
|
PARSER_CATCH
|
|
{
|
|
#if JERRY_ESNEXT
|
|
while (scanner_context.active_binding_list_p != NULL)
|
|
{
|
|
scanner_pop_binding_list (&scanner_context);
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (JERRY_UNLIKELY (context_p->error != PARSER_ERR_OUT_OF_MEMORY))
|
|
{
|
|
/* Ignore the errors thrown by the lexer. */
|
|
context_p->error = PARSER_ERR_NO_ERROR;
|
|
|
|
/* The following code may allocate memory, so it is enclosed in a try/catch. */
|
|
PARSER_TRY (context_p->try_buffer)
|
|
{
|
|
#if JERRY_ESNEXT
|
|
if (scanner_context.status_flags & SCANNER_CONTEXT_THROW_ERR_ASYNC_FUNCTION)
|
|
{
|
|
JERRY_ASSERT (scanner_context.async_source_p != NULL);
|
|
|
|
scanner_info_t *info_p;
|
|
info_p = scanner_insert_info (context_p, scanner_context.async_source_p, sizeof (scanner_info_t));
|
|
info_p->type = SCANNER_TYPE_ERR_ASYNC_FUNCTION;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
while (scanner_context.active_literal_pool_p != NULL)
|
|
{
|
|
scanner_pop_literal_pool (context_p, &scanner_context);
|
|
}
|
|
}
|
|
PARSER_CATCH
|
|
{
|
|
JERRY_ASSERT (context_p->error == PARSER_ERR_OUT_OF_MEMORY);
|
|
}
|
|
PARSER_TRY_END
|
|
}
|
|
|
|
JERRY_ASSERT (context_p->error == PARSER_ERR_NO_ERROR || context_p->error == PARSER_ERR_OUT_OF_MEMORY);
|
|
|
|
if (context_p->error == PARSER_ERR_OUT_OF_MEMORY)
|
|
{
|
|
while (scanner_context.active_literal_pool_p != NULL)
|
|
{
|
|
scanner_literal_pool_t *literal_pool_p = scanner_context.active_literal_pool_p;
|
|
|
|
scanner_context.active_literal_pool_p = literal_pool_p->prev_p;
|
|
|
|
parser_list_free (&literal_pool_p->literal_pool);
|
|
scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
|
|
}
|
|
|
|
parser_stack_free (context_p);
|
|
return;
|
|
}
|
|
}
|
|
PARSER_TRY_END
|
|
|
|
context_p->status_flags = scanner_context.context_status_flags;
|
|
#if JERRY_ESNEXT
|
|
context_p->global_status_flags &= (uint32_t) ~ECMA_PARSE_INTERNAL_PRE_SCANNING;
|
|
#endif /* JERRY_ESNEXT */
|
|
scanner_reverse_info_list (context_p);
|
|
|
|
#if JERRY_PARSER_DUMP_BYTE_CODE
|
|
if (context_p->is_show_opcodes)
|
|
{
|
|
scanner_info_t *info_p = context_p->next_scanner_info_p;
|
|
const uint8_t *source_start_p =
|
|
(context_p->arguments_start_p == NULL ? context_p->source_start_p : context_p->arguments_start_p);
|
|
|
|
while (info_p->type != SCANNER_TYPE_END)
|
|
{
|
|
const char *name_p = NULL;
|
|
bool print_location = false;
|
|
|
|
switch (info_p->type)
|
|
{
|
|
case SCANNER_TYPE_END_ARGUMENTS:
|
|
{
|
|
JERRY_DEBUG_MSG (" END_ARGUMENTS\n");
|
|
source_start_p = context_p->source_start_p;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_FUNCTION:
|
|
case SCANNER_TYPE_BLOCK:
|
|
{
|
|
const uint8_t *prev_source_p = info_p->source_p - 1;
|
|
const uint8_t *data_p;
|
|
|
|
if (info_p->type == SCANNER_TYPE_FUNCTION)
|
|
{
|
|
data_p = (const uint8_t *) (info_p + 1);
|
|
|
|
JERRY_DEBUG_MSG (" FUNCTION: flags: 0x%x declarations: %d", (int) info_p->u8_arg, (int) info_p->u16_arg);
|
|
}
|
|
else
|
|
{
|
|
data_p = (const uint8_t *) (info_p + 1);
|
|
|
|
JERRY_DEBUG_MSG (" BLOCK:");
|
|
}
|
|
|
|
JERRY_DEBUG_MSG (" source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
|
|
while (data_p[0] != SCANNER_STREAM_TYPE_END)
|
|
{
|
|
switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
|
|
{
|
|
case SCANNER_STREAM_TYPE_HOLE:
|
|
{
|
|
JERRY_DEBUG_MSG (" HOLE\n");
|
|
data_p++;
|
|
continue;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_STREAM_TYPE_ARGUMENTS:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARGUMENTS%s%s\n",
|
|
(data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "",
|
|
(data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : "");
|
|
data_p++;
|
|
continue;
|
|
}
|
|
case SCANNER_STREAM_TYPE_ARGUMENTS_FUNC:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARGUMENTS_FUNC%s%s\n",
|
|
(data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "",
|
|
(data_p[0] & SCANNER_STREAM_LOCAL_ARGUMENTS) ? " L" : "");
|
|
data_p++;
|
|
continue;
|
|
}
|
|
#else /* !JERRY_ESNEXT */
|
|
case SCANNER_STREAM_TYPE_ARGUMENTS:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARGUMENTS%s\n", (data_p[0] & SCANNER_STREAM_NO_REG) ? " *" : "");
|
|
data_p++;
|
|
continue;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCANNER_STREAM_TYPE_VAR:
|
|
{
|
|
JERRY_DEBUG_MSG (" VAR ");
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_STREAM_TYPE_LET:
|
|
{
|
|
JERRY_DEBUG_MSG (" LET ");
|
|
break;
|
|
}
|
|
case SCANNER_STREAM_TYPE_CONST:
|
|
{
|
|
JERRY_DEBUG_MSG (" CONST ");
|
|
break;
|
|
}
|
|
case SCANNER_STREAM_TYPE_LOCAL:
|
|
{
|
|
JERRY_DEBUG_MSG (" LOCAL ");
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
#if JERRY_MODULE_SYSTEM
|
|
case SCANNER_STREAM_TYPE_IMPORT:
|
|
{
|
|
JERRY_DEBUG_MSG (" IMPORT ");
|
|
break;
|
|
}
|
|
#endif /* JERRY_MODULE_SYSTEM */
|
|
case SCANNER_STREAM_TYPE_ARG:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARG ");
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_STREAM_TYPE_ARG_VAR:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARG_VAR ");
|
|
break;
|
|
}
|
|
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
|
|
{
|
|
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG ");
|
|
break;
|
|
}
|
|
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
|
|
{
|
|
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_VAR ");
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCANNER_STREAM_TYPE_ARG_FUNC:
|
|
{
|
|
JERRY_DEBUG_MSG (" ARG_FUNC ");
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
|
|
{
|
|
JERRY_DEBUG_MSG (" DESTRUCTURED_ARG_FUNC ");
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCANNER_STREAM_TYPE_FUNC:
|
|
{
|
|
JERRY_DEBUG_MSG (" FUNC ");
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
JERRY_UNREACHABLE ();
|
|
data_p++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
size_t length;
|
|
|
|
if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
|
|
{
|
|
if (data_p[2] != 0)
|
|
{
|
|
prev_source_p += data_p[2];
|
|
length = 2 + 1;
|
|
}
|
|
else
|
|
{
|
|
memcpy (&prev_source_p, data_p + 2 + 1, sizeof (uintptr_t));
|
|
length = 2 + 1 + sizeof (uintptr_t);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
|
|
|
|
if (diff <= UINT8_MAX)
|
|
{
|
|
diff = -diff;
|
|
}
|
|
|
|
prev_source_p += diff;
|
|
length = 2 + 2;
|
|
}
|
|
|
|
#if JERRY_ESNEXT
|
|
if (data_p[0] & SCANNER_STREAM_EARLY_CREATE)
|
|
{
|
|
JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
|
|
JERRY_DEBUG_MSG ("*");
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
|
|
if (data_p[0] & SCANNER_STREAM_NO_REG)
|
|
{
|
|
JERRY_DEBUG_MSG ("* ");
|
|
}
|
|
|
|
JERRY_DEBUG_MSG ("'%.*s'\n", data_p[1], (char *) prev_source_p);
|
|
prev_source_p += data_p[1];
|
|
data_p += length;
|
|
}
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_WHILE:
|
|
{
|
|
name_p = "WHILE";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_FOR:
|
|
{
|
|
scanner_for_info_t *for_info_p = (scanner_for_info_t *) info_p;
|
|
JERRY_DEBUG_MSG (" FOR: source:%d expression:%d[%d:%d] end:%d[%d:%d]\n",
|
|
(int) (for_info_p->info.source_p - source_start_p),
|
|
(int) (for_info_p->expression_location.source_p - source_start_p),
|
|
(int) for_info_p->expression_location.line,
|
|
(int) for_info_p->expression_location.column,
|
|
(int) (for_info_p->end_location.source_p - source_start_p),
|
|
(int) for_info_p->end_location.line,
|
|
(int) for_info_p->end_location.column);
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_FOR_IN:
|
|
{
|
|
name_p = "FOR-IN";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_TYPE_FOR_OF:
|
|
{
|
|
name_p = "FOR-OF";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
case SCANNER_TYPE_SWITCH:
|
|
{
|
|
JERRY_DEBUG_MSG (" SWITCH: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
|
|
scanner_case_info_t *current_case_p = ((scanner_switch_info_t *) info_p)->case_p;
|
|
|
|
while (current_case_p != NULL)
|
|
{
|
|
JERRY_DEBUG_MSG (" CASE: location:%d[%d:%d]\n",
|
|
(int) (current_case_p->location.source_p - source_start_p),
|
|
(int) current_case_p->location.line,
|
|
(int) current_case_p->location.column);
|
|
|
|
current_case_p = current_case_p->next_p;
|
|
}
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_CASE:
|
|
{
|
|
name_p = "CASE";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
#if JERRY_ESNEXT
|
|
case SCANNER_TYPE_INITIALIZER:
|
|
{
|
|
scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p;
|
|
JERRY_DEBUG_MSG (" INITIALIZER: flags: 0x%x source:%d location:%d[%d:%d]\n",
|
|
(int) info_p->u8_arg,
|
|
(int) (location_info_p->info.source_p - source_start_p),
|
|
(int) (location_info_p->location.source_p - source_start_p),
|
|
(int) location_info_p->location.line,
|
|
(int) location_info_p->location.column);
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_CLASS_CONSTRUCTOR:
|
|
{
|
|
JERRY_DEBUG_MSG (" CLASS: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
print_location = false;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_CLASS_STATIC_BLOCK_END:
|
|
{
|
|
name_p = "SCANNER_TYPE_CLASS_STATIC_BLOCK_END";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END:
|
|
{
|
|
name_p = "SCANNER_TYPE_CLASS_FIELD_INITIALIZER_END";
|
|
print_location = true;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_LET_EXPRESSION:
|
|
{
|
|
JERRY_DEBUG_MSG (" LET_EXPRESSION: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_ERR_REDECLARED:
|
|
{
|
|
JERRY_DEBUG_MSG (" JERRY_FATAL_REDECLARED: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_ERR_ASYNC_FUNCTION:
|
|
{
|
|
JERRY_DEBUG_MSG (" JERRY_FATAL_ASYNC_FUNCTION: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_LITERAL_FLAGS:
|
|
{
|
|
JERRY_DEBUG_MSG (" SCANNER_TYPE_LITERAL_FLAGS: flags: 0x%x source:%d\n",
|
|
(int) info_p->u8_arg,
|
|
(int) (info_p->source_p - source_start_p));
|
|
print_location = false;
|
|
break;
|
|
}
|
|
case SCANNER_TYPE_EXPORT_MODULE_SPECIFIER:
|
|
{
|
|
JERRY_DEBUG_MSG (" EXPORT_WITH_MODULE_SPECIFIER: source:%d\n", (int) (info_p->source_p - source_start_p));
|
|
print_location = false;
|
|
break;
|
|
}
|
|
#endif /* JERRY_ESNEXT */
|
|
}
|
|
|
|
if (print_location)
|
|
{
|
|
scanner_location_info_t *location_info_p = (scanner_location_info_t *) info_p;
|
|
JERRY_DEBUG_MSG (" %s: source:%d location:%d[%d:%d]\n",
|
|
name_p,
|
|
(int) (location_info_p->info.source_p - source_start_p),
|
|
(int) (location_info_p->location.source_p - source_start_p),
|
|
(int) location_info_p->location.line,
|
|
(int) location_info_p->location.column);
|
|
}
|
|
|
|
info_p = info_p->next_p;
|
|
}
|
|
|
|
JERRY_DEBUG_MSG ("\n--- Scanning end ---\n\n");
|
|
}
|
|
#endif /* JERRY_PARSER_DUMP_BYTE_CODE */
|
|
|
|
parser_stack_free (context_p);
|
|
} /* scanner_scan_all */
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
* @}
|
|
*/
|
|
|
|
#endif /* JERRY_PARSER */
|