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,
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) {
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);
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);
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)) {
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)) {
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);
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 {
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");
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;
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;
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;
}