From: hongzhidao Date: Sat, 9 Feb 2019 09:34:04 +0000 (+0800) Subject: Refactored njs_parser_terminal(). X-Git-Tag: 0.2.8~29 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=4af7b1f9b277f98d017eec2a068749c1393b1b7f;p=njs.git Refactored njs_parser_terminal(). 1) Introduced njs_parser_reference(). 2) njs_parser_builtin_object() and njs_parser_builtin_function() are refactored into njs_parser_builtin(). 3) njs_parser_external() is simplified and renamed as njs_external_lookup(). --- diff --git a/njs/njs_extern.c b/njs/njs_extern.c index 503fd0bc..d9552f2b 100644 --- a/njs/njs_extern.c +++ b/njs/njs_extern.c @@ -304,13 +304,13 @@ njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external) njs_value_t * -njs_parser_external(njs_vm_t *vm, njs_parser_t *parser) +njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash) { nxt_lvlhsh_query_t lhq; njs_extern_value_t *ev; - lhq.key_hash = parser->lexer->key_hash; - lhq.key = parser->lexer->text; + lhq.key_hash = hash; + lhq.key = *name; lhq.proto = &njs_extern_value_hash_proto; if (nxt_lvlhsh_find(&vm->externals_hash, &lhq) == NXT_OK) { diff --git a/njs/njs_extern.h b/njs/njs_extern.h index 542d97c8..0e00fb4d 100644 --- a/njs/njs_extern.h +++ b/njs/njs_extern.h @@ -42,6 +42,7 @@ typedef struct { njs_array_t *njs_extern_keys_array(njs_vm_t *vm, const njs_extern_t *external); +njs_value_t *njs_external_lookup(njs_vm_t *vm, nxt_str_t *name, uint32_t hash); nxt_int_t njs_external_match_native_function(njs_vm_t *vm, njs_function_native_t func, nxt_str_t *name); diff --git a/njs/njs_parser.c b/njs/njs_parser.c index 6c5d7fef..31c9c725 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -52,10 +52,11 @@ static njs_token_t njs_parser_throw_statement(njs_vm_t *vm, njs_parser_t *parser); static njs_token_t njs_parser_grouping_expression(njs_vm_t *vm, njs_parser_t *parser); -static njs_token_t njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node); -static njs_token_t njs_parser_builtin_function(njs_vm_t *vm, - njs_parser_t *parser, njs_parser_node_t *node); +static njs_parser_node_t *njs_parser_reference(njs_vm_t *vm, + njs_parser_t *parser, njs_token_t token, nxt_str_t *name, uint32_t hash); +static nxt_int_t njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, + njs_parser_node_t *node, njs_value_type_t type, nxt_str_t *name, + uint32_t hash); static njs_token_t njs_parser_object(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *obj); static njs_token_t njs_parser_array(njs_vm_t *vm, njs_parser_t *parser, @@ -1808,11 +1809,12 @@ njs_parser_token(njs_parser_t *parser) njs_token_t njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) { - double num; - njs_ret_t ret; - njs_value_t *ext; - njs_parser_node_t *node; - njs_parser_scope_t *scope; + double num; + njs_ret_t ret; + njs_lexer_t *lexer; + njs_parser_node_t *node; + + lexer = parser->lexer; if (token == NJS_TOKEN_OPEN_PARENTHESIS) { @@ -1833,37 +1835,16 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) return njs_parser_function_expression(vm, parser); } - node = njs_parser_node_new(vm, parser, token); - if (nxt_slow_path(node == NULL)) { - return NJS_TOKEN_ERROR; - } - switch (token) { - case NJS_TOKEN_NAME: - nxt_thread_log_debug("JS: %V", &parser->lexer->text); - - ext = njs_parser_external(vm, parser); - - if (ext != NULL) { - node->token = NJS_TOKEN_EXTERNAL; - node->u.value = *ext; - node->index = (njs_index_t) ext; - break; - } + case NJS_TOKEN_OPEN_BRACE: + nxt_thread_log_debug("JS: OBJECT"); - ret = njs_parser_variable_reference(vm, parser, node, NJS_REFERENCE); - if (nxt_slow_path(ret != NXT_OK)) { + node = njs_parser_node_new(vm, parser, NJS_TOKEN_OBJECT); + if (nxt_slow_path(node == NULL)) { return NJS_TOKEN_ERROR; } - break; - - case NJS_TOKEN_OPEN_BRACE: - node->token = NJS_TOKEN_OBJECT; - - nxt_thread_log_debug("JS: OBJECT"); - parser->node = node; token = njs_parser_object(vm, parser, node); @@ -1877,10 +1858,13 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) return token; case NJS_TOKEN_OPEN_BRACKET: - node->token = NJS_TOKEN_ARRAY; - nxt_thread_log_debug("JS: ARRAY"); + node = njs_parser_node_new(vm, parser, NJS_TOKEN_ARRAY); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + parser->node = node; token = njs_parser_array(vm, parser, node); @@ -1894,19 +1878,27 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) return token; case NJS_TOKEN_DIVISION: + node = njs_parser_node_new(vm, parser, NJS_TOKEN_REGEXP); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + token = njs_regexp_literal(vm, parser, &node->u.value); if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) { return token; } - nxt_thread_log_debug("REGEX: '%V'", &parser->lexer->text); - - node->token = NJS_TOKEN_REGEXP; + nxt_thread_log_debug("REGEX: '%V'", &lexer->text); break; case NJS_TOKEN_STRING: - nxt_thread_log_debug("JS: '%V'", &parser->lexer->text); + nxt_thread_log_debug("JS: '%V'", &lexer->text); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } ret = njs_parser_string_create(vm, &node->u.value); if (nxt_slow_path(ret != NXT_OK)) { @@ -1916,9 +1908,12 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) break; case NJS_TOKEN_ESCAPE_STRING: - node->token = NJS_TOKEN_STRING; + nxt_thread_log_debug("JS: '%V'", &lexer->text); - nxt_thread_log_debug("JS: '%V'", &parser->lexer->text); + node = njs_parser_node_new(vm, parser, NJS_TOKEN_STRING); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } ret = njs_parser_escape_string_create(vm, parser, &node->u.value); if (nxt_slow_path(ret != NJS_TOKEN_STRING)) { @@ -1929,14 +1924,19 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) case NJS_TOKEN_UNTERMINATED_STRING: njs_parser_syntax_error(vm, parser, "Unterminated string \"%V\"", - &parser->lexer->text); + &lexer->text); return NJS_TOKEN_ILLEGAL; case NJS_TOKEN_NUMBER: - nxt_thread_log_debug("JS: %f", parser->lexer->number); + num = lexer->number; + nxt_thread_log_debug("JS: %f", num); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_NUMBER); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } - num = parser->lexer->number; node->u.value.data.u.number = num; node->u.value.type = NJS_NUMBER; node->u.value.data.truth = njs_is_number_true(num); @@ -1944,9 +1944,14 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) break; case NJS_TOKEN_BOOLEAN: - nxt_thread_log_debug("JS: boolean: %V", &parser->lexer->text); + nxt_thread_log_debug("JS: boolean: %V", &lexer->text); + + node = njs_parser_node_new(vm, parser, NJS_TOKEN_BOOLEAN); + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } - if (parser->lexer->number == 0) { + if (lexer->number == 0) { node->u.value = njs_value_false; } else { @@ -1955,6 +1960,39 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) break; + default: + node = njs_parser_reference(vm, parser, token, &lexer->text, + lexer->key_hash); + + if (nxt_slow_path(node == NULL)) { + return NJS_TOKEN_ERROR; + } + + break; + } + + parser->node = node; + + return njs_parser_token(parser); +} + + +static njs_parser_node_t * +njs_parser_reference(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, + nxt_str_t *name, uint32_t hash) +{ + njs_ret_t ret; + njs_value_t *ext; + njs_parser_node_t *node; + njs_parser_scope_t *scope; + + node = njs_parser_node_new(vm, parser, token); + if (nxt_slow_path(node == NULL)) { + return NULL; + } + + switch (token) { + case NJS_TOKEN_NULL: nxt_thread_log_debug("JS: null"); @@ -1992,16 +2030,21 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) case NJS_TOKEN_NJS: case NJS_TOKEN_MATH: case NJS_TOKEN_JSON: - return njs_parser_builtin_object(vm, parser, node); + ret = njs_parser_builtin(vm, parser, node, NJS_OBJECT, name, hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + break; case NJS_TOKEN_ARGUMENTS: nxt_thread_log_debug("JS: arguments"); if (parser->scope->type <= NJS_SCOPE_GLOBAL) { njs_parser_syntax_error(vm, parser, "\"%V\" object " - "in global scope", &parser->lexer->text); + "in global scope", name); - return NJS_TOKEN_ILLEGAL; + return NULL; } break; @@ -2088,66 +2131,46 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token) case NJS_TOKEN_SET_TIMEOUT: case NJS_TOKEN_SET_IMMEDIATE: case NJS_TOKEN_CLEAR_TIMEOUT: - return njs_parser_builtin_function(vm, parser, node); - - default: - return njs_parser_unexpected_token(vm, parser, token); - } - - parser->node = node; - - return njs_parser_token(parser); -} - + ret = njs_parser_builtin(vm, parser, node, NJS_FUNCTION, name, hash); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } -static njs_token_t -njs_parser_builtin_object(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node) -{ - uint32_t hash; - nxt_str_t *name; - njs_ret_t ret; - nxt_uint_t index; - njs_variable_t *var; - njs_parser_scope_t *scope; + break; - scope = parser->scope; + case NJS_TOKEN_NAME: + nxt_thread_log_debug("JS: %V", name); - while (scope->type != NJS_SCOPE_GLOBAL) { - scope = scope->parent; - } + ext = njs_external_lookup(vm, name, hash); - hash = parser->lexer->key_hash; - name = &parser->lexer->text; + if (ext != NULL) { + node->token = NJS_TOKEN_EXTERNAL; + node->u.value = *ext; + node->index = (njs_index_t) ext; + break; + } - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); - if (nxt_slow_path(var == NULL)) { - return NJS_TOKEN_ERROR; - } + ret = njs_variable_reference(vm, parser->scope, node, name, hash, + NJS_REFERENCE); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } - /* TODO: once */ - index = node->token - NJS_TOKEN_FIRST_OBJECT; - var->value.data.u.object = &vm->shared->objects[index]; - var->value.type = NJS_OBJECT; - var->value.data.truth = 1; + break; - ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE); - if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; + default: + (void) njs_parser_unexpected_token(vm, parser, token); + return NULL; } - parser->node = node; - - return njs_parser_token(parser); + return node; } -static njs_token_t -njs_parser_builtin_function(njs_vm_t *vm, njs_parser_t *parser, - njs_parser_node_t *node) +static nxt_int_t +njs_parser_builtin(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node, + njs_value_type_t type, nxt_str_t *name, uint32_t hash) { - uint32_t hash; - nxt_str_t *name; njs_ret_t ret; nxt_uint_t index; njs_variable_t *var; @@ -2159,28 +2182,36 @@ njs_parser_builtin_function(njs_vm_t *vm, njs_parser_t *parser, scope = scope->parent; } - hash = parser->lexer->key_hash; - name = &parser->lexer->text; - var = njs_variable_add(vm, scope, name, hash, NJS_VARIABLE_VAR); if (nxt_slow_path(var == NULL)) { - return NJS_TOKEN_ERROR; + return NXT_ERROR; } /* TODO: once */ - index = node->token - NJS_TOKEN_FIRST_FUNCTION; - var->value.data.u.function = &vm->shared->functions[index]; - var->value.type = NJS_FUNCTION; + switch (type) { + case NJS_OBJECT: + index = node->token - NJS_TOKEN_FIRST_OBJECT; + var->value.data.u.object = &vm->shared->objects[index]; + break; + + case NJS_FUNCTION: + index = node->token - NJS_TOKEN_FIRST_FUNCTION; + var->value.data.u.function = &vm->shared->functions[index]; + break; + + default: + return NXT_ERROR; + } + + var->value.type = type; var->value.data.truth = 1; ret = njs_variable_reference(vm, scope, node, name, hash, NJS_REFERENCE); if (nxt_slow_path(ret != NXT_OK)) { - return NJS_TOKEN_ERROR; + return NXT_ERROR; } - parser->node = node; - - return njs_parser_token(parser); + return NXT_OK; } diff --git a/njs/njs_parser.h b/njs/njs_parser.h index 30d04a55..a2b536fd 100644 --- a/njs/njs_parser.h +++ b/njs/njs_parser.h @@ -306,8 +306,6 @@ void njs_lexer_rollback(njs_lexer_t *lexer); nxt_int_t njs_lexer_keywords_init(nxt_mp_t *mcp, nxt_lvlhsh_t *hash); njs_token_t njs_lexer_keyword(njs_lexer_t *lexer); -njs_value_t *njs_parser_external(njs_vm_t *vm, njs_parser_t *parser); - nxt_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser, njs_parser_t *prev); njs_token_t njs_parser_arguments(njs_vm_t *vm, njs_parser_t *parser,