[njs] For and for-in loops support variable declaration.
Igor Sysoev
igor at sysoev.ru
Tue Jan 3 15:35:29 UTC 2017
details: http://hg.nginx.org/njs/rev/6c5bebb914ef
branches:
changeset: 294:6c5bebb914ef
user: Igor Sysoev <igor at sysoev.ru>
date: Mon Jan 02 22:59:29 2017 +0300
description:
For and for-in loops support variable declaration.
diffstat:
njs/njs_parser.c | 218 +++++++++++++++++++++++++++++++++++++++++-----
njs/test/njs_unit_test.c | 13 ++
2 files changed, 205 insertions(+), 26 deletions(-)
diffs (272 lines):
diff -r 4337ed48d6d6 -r 6c5bebb914ef njs/njs_parser.c
--- a/njs/njs_parser.c Mon Jan 02 22:59:24 2017 +0300
+++ b/njs/njs_parser.c Mon Jan 02 22:59:29 2017 +0300
@@ -64,6 +64,10 @@ static njs_token_t njs_parser_while_stat
static njs_token_t njs_parser_do_while_statement(njs_vm_t *vm,
njs_parser_t *parser);
static njs_token_t njs_parser_for_statement(njs_vm_t *vm, njs_parser_t *parser);
+static njs_token_t njs_parser_for_var_statement(njs_vm_t *vm,
+ njs_parser_t *parser);
+static njs_token_t njs_parser_for_var_in_statement(njs_vm_t *vm,
+ njs_parser_t *parser, njs_parser_node_t *name);
static njs_token_t njs_parser_for_in_statement(njs_vm_t *vm,
njs_parser_t *parser, nxt_str_t *name, njs_token_t token);
static njs_token_t njs_parser_continue_statement(njs_vm_t *vm,
@@ -1122,17 +1126,34 @@ njs_parser_for_statement(njs_vm_t *vm, n
}
if (token != NJS_TOKEN_SEMICOLON) {
- name = parser->lexer->text;
-
- token = njs_parser_expression(vm, parser, token);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
- init = parser->node;
-
- if (init->token == NJS_TOKEN_IN) {
- return njs_parser_for_in_statement(vm, parser, &name, token);
+
+ if (token == NJS_TOKEN_VAR) {
+
+ token = njs_parser_for_var_statement(vm, parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ init = parser->node;
+
+ if (init->token == NJS_TOKEN_FOR_IN) {
+ return token;
+ }
+
+ } else {
+
+ name = parser->lexer->text;
+
+ token = njs_parser_expression(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ init = parser->node;
+
+ if (init->token == NJS_TOKEN_IN) {
+ return njs_parser_for_in_statement(vm, parser, &name, token);
+ }
}
}
@@ -1148,21 +1169,21 @@ njs_parser_for_statement(njs_vm_t *vm, n
return token;
}
- condition = parser->node;
- }
-
- token = njs_parser_match(vm, parser, token, NJS_TOKEN_SEMICOLON);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
- if (token != NJS_TOKEN_CLOSE_PARENTHESIS) {
-
- token = njs_parser_expression(vm, parser, token);
- if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
- return token;
- }
-
+ condition = parser->node;
+ }
+
+ token = njs_parser_match(vm, parser, token, NJS_TOKEN_SEMICOLON);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ if (token != NJS_TOKEN_CLOSE_PARENTHESIS) {
+
+ token = njs_parser_expression(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
update = parser->node;
}
@@ -1209,6 +1230,151 @@ njs_parser_for_statement(njs_vm_t *vm, n
static njs_token_t
+njs_parser_for_var_statement(njs_vm_t *vm, njs_parser_t *parser)
+{
+ njs_ret_t ret;
+ njs_token_t token;
+ njs_variable_t *var;
+ njs_parser_node_t *left, *stmt, *name, *assign, *expr;
+
+ parser->node = NULL;
+ left = NULL;
+
+ do {
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ if (token != NJS_TOKEN_NAME) {
+ return NJS_TOKEN_ILLEGAL;
+ }
+
+ var = njs_variable_add(vm, parser, NJS_VARIABLE_VAR);
+ if (nxt_slow_path(var == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ name = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(name == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ name->token = NJS_TOKEN_NAME;
+
+ ret = njs_variable_reference(vm, parser, name);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ if (token == NJS_TOKEN_IN) {
+ return njs_parser_for_var_in_statement(vm, parser, name);
+ }
+
+ expr = NULL;
+
+ if (token == NJS_TOKEN_ASSIGNMENT) {
+
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ token = njs_parser_var_expression(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ expr = parser->node;
+ }
+
+ assign = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(assign == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ assign->token = NJS_TOKEN_VAR;
+ assign->u.operation = njs_vmcode_move;
+ assign->left = name;
+ assign->right = expr;
+
+ stmt = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(stmt == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ stmt->token = NJS_TOKEN_STATEMENT;
+ stmt->left = left;
+ stmt->right = assign;
+ parser->node = stmt;
+ parser->code_size += sizeof(njs_vmcode_2addr_t);
+
+ left = stmt;
+
+ } while (token == NJS_TOKEN_COMMA);
+
+ return token;
+}
+
+
+static njs_token_t
+njs_parser_for_var_in_statement(njs_vm_t *vm, njs_parser_t *parser,
+ njs_parser_node_t *name)
+{
+ njs_token_t token;
+ njs_parser_node_t *node, *foreach;
+
+ token = njs_parser_token(parser);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ token = njs_parser_expression(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ node = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(node == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ node->token = NJS_TOKEN_IN;
+ node->left = name;
+ node->right = parser->node;
+
+ token = njs_parser_match(vm, parser, token, NJS_TOKEN_CLOSE_PARENTHESIS);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ token = njs_parser_statement(vm, parser, token);
+ if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
+ return token;
+ }
+
+ foreach = njs_parser_node_alloc(vm);
+ if (nxt_slow_path(foreach == NULL)) {
+ return NJS_TOKEN_ERROR;
+ }
+
+ foreach->token = NJS_TOKEN_FOR_IN;
+ foreach->left = node;
+ foreach->right = parser->node;
+
+ parser->node = foreach;
+ parser->code_size += sizeof(njs_vmcode_prop_foreach_t)
+ + sizeof(njs_vmcode_prop_next_t);
+ return token;
+}
+
+
+static njs_token_t
njs_parser_for_in_statement(njs_vm_t *vm, njs_parser_t *parser, nxt_str_t *name,
njs_token_t token)
{
diff -r 4337ed48d6d6 -r 6c5bebb914ef njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Mon Jan 02 22:59:24 2017 +0300
+++ b/njs/test/njs_unit_test.c Mon Jan 02 22:59:29 2017 +0300
@@ -4506,6 +4506,19 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("function f(a) { return a } var a = '2'; a + f(5)"),
nxt_string("25") },
+ { nxt_string("for (var i = 0; i < 5; i++); i"),
+ nxt_string("5") },
+
+ { nxt_string("for (var i = 0, j; i < 5; i++); j"),
+ nxt_string("undefined") },
+
+ { nxt_string("for (var i = 0, j, k = 3; i < 5; i++); k"),
+ nxt_string("3") },
+
+ { nxt_string("var o = { a: 1, b: 2, c: 3 }, s = ''; "
+ "for (var i in o) { s += i }; s"),
+ nxt_string("abc") },
+
/* RegExp. */
{ nxt_string("/./x"),
More information about the nginx-devel
mailing list