From 1e1a74d45fcd5c8bbfd0bdef596802574f173d8e Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Thu, 4 Jun 2020 17:26:01 +0300 Subject: [PATCH] Parser: added line positions for AST nodes. --- src/njs_lexer.c | 4 +- src/njs_parser.c | 416 +++++++++++++++++++++++++++++++---------------- src/njs_parser.h | 2 + 3 files changed, 276 insertions(+), 146 deletions(-) diff --git a/src/njs_lexer.c b/src/njs_lexer.c index 215f005e..5f445ce7 100644 --- a/src/njs_lexer.c +++ b/src/njs_lexer.c @@ -449,6 +449,7 @@ njs_lexer_make_token(njs_lexer_t *lexer, njs_lexer_token_t *token) } token->type = njs_tokens[c]; + token->line = lexer->line; switch (token->type) { @@ -566,7 +567,6 @@ njs_lexer_make_token(njs_lexer_t *lexer, njs_lexer_token_t *token) /* Fall through. */ default: - token->line = lexer->line; token->text.start = lexer->start - 1; token->text.length = lexer->start - token->text.start; @@ -668,7 +668,6 @@ njs_lexer_word(njs_lexer_t *lexer, njs_lexer_token_t *token) 0x00, 0x00, 0x00, 0x00, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ }; - token->line = lexer->line; token->text.start = lexer->start - 1; hash_id = njs_djb_hash_add(NJS_DJB_HASH_INIT, *token->text.start); @@ -866,6 +865,7 @@ njs_lexer_multi(njs_lexer_t *lexer, njs_lexer_token_t *token, { u_char c; + token->line = lexer->line; token->text.start = lexer->start - 1; while (length != 0 && multi != NULL && lexer->start < lexer->end) { diff --git a/src/njs_parser.c b/src/njs_parser.c index 711bad9c..28f97137 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -563,6 +563,7 @@ njs_parser(njs_parser_t *parser, njs_parser_t *prev) } parser->node->token_type = NJS_TOKEN_END; + parser->node->token_line = parser->lexer->line; njs_parser_chain_top_set(parser, parser->node); @@ -921,6 +922,17 @@ njs_parser_expression_parenthesis(njs_parser_t *parser, } +static njs_int_t +njs_parser_set_line_state(njs_parser_t *parser, + njs_lexer_token_t *token, njs_queue_link_t *current) +{ + parser->node->token_line = (uint32_t) (uintptr_t) parser->target; + parser->target = NULL; + + return njs_parser_stack_pop(parser); +} + + /* * 12.2 Primary Expression. */ @@ -948,6 +960,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser, } node->u.value = njs_value_true; + node->token_line = token->line; parser->node = node; goto done; @@ -959,6 +972,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser, } node->u.value = njs_value_false; + node->token_line = token->line; parser->node = node; goto done; @@ -970,6 +984,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser, } njs_set_number(&node->u.value, token->number); + node->token_line = token->line; parser->node = node; goto done; @@ -980,6 +995,8 @@ njs_parser_primary_expression_test(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; + ret = njs_parser_string_create(parser->vm, token, &node->u.value); if (ret != NJS_OK) { return NJS_ERROR; @@ -996,6 +1013,8 @@ njs_parser_primary_expression_test(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; + ret = njs_parser_escape_string_create(parser, token, &node->u.value); if (ret != NJS_TOKEN_STRING) { return NJS_ERROR; @@ -1013,11 +1032,27 @@ njs_parser_primary_expression_test(njs_parser_t *parser, /* ArrayLiteral */ case NJS_TOKEN_OPEN_BRACKET: + node = njs_parser_node_new(parser, NJS_TOKEN_ARRAY); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + parser->node = node; + njs_parser_next(parser, njs_parser_array_literal); break; /* ObjectLiteral */ case NJS_TOKEN_OPEN_BRACE: + node = njs_parser_node_new(parser, NJS_TOKEN_OBJECT); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + parser->node = node; + njs_parser_next(parser, njs_parser_object_literal); break; @@ -1039,7 +1074,6 @@ njs_parser_primary_expression_test(njs_parser_t *parser, } node->token_line = token->line; - parser->node = node; njs_parser_next(parser, njs_parser_function_expression); @@ -1086,6 +1120,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; parser->node = node; ret = njs_parser_regexp_literal(parser, token, current); @@ -1102,6 +1137,7 @@ njs_parser_primary_expression_test(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; parser->node = node; njs_parser_next(parser, njs_parser_template_literal); @@ -1140,6 +1176,7 @@ reference: return NJS_ERROR; } + node->token_line = token->line; parser->node = node; done: @@ -1259,6 +1296,8 @@ njs_parser_template_literal(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + array->token_line = token->line; + template = parser->node; index = NJS_SCOPE_CALLEE_ARGUMENTS; @@ -1532,14 +1571,8 @@ static njs_int_t njs_parser_array_literal(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *array; - - array = njs_parser_node_new(parser, NJS_TOKEN_ARRAY); - if (array == NULL) { - return NJS_ERROR; - } - - parser->target = array; + parser->target = parser->node; + parser->node = NULL; njs_parser_next(parser, njs_parser_array_element_list); @@ -1644,20 +1677,16 @@ static njs_int_t njs_parser_object_literal(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *object, *node; - - object = njs_parser_node_new(parser, NJS_TOKEN_OBJECT); - if (object == NULL) { - return NJS_ERROR; - } + njs_parser_node_t *node; node = njs_parser_node_new(parser, 0); if (node == NULL) { return NJS_ERROR; } - node->left = object; + node->left = parser->node; + parser->node = NULL; parser->target = node; njs_parser_next(parser, njs_parser_property_definition_list); @@ -1750,6 +1779,10 @@ njs_parser_property_name_node(njs_parser_t *parser, njs_lexer_token_t *token) property = njs_parser_node_string(parser->vm, token, parser); } + if (property != NULL) { + property->token_line = token->line; + } + return property; } @@ -2103,8 +2136,6 @@ njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token, switch (token->type) { case NJS_TOKEN_OPEN_BRACKET: - njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY); if (node == NULL) { return NJS_ERROR; @@ -2112,9 +2143,12 @@ njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token, node->u.operation = NJS_VMCODE_PROPERTY_GET; node->left = parser->node; + node->token_line = token->line; parser->node = NULL; + njs_lexer_consume_token(parser->lexer, 1); + njs_parser_next(parser, njs_parser_expression); return njs_parser_after(parser, current, node, 1, @@ -2133,12 +2167,15 @@ njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token, } node->u.operation = NJS_VMCODE_PROPERTY_GET; + node->token_line = token->line; prop_node = njs_parser_node_string(parser->vm, token, parser); if (prop_node == NULL) { return NJS_ERROR; } + prop_node->token_line = token->line; + node->left = parser->node; node->right = prop_node; @@ -2153,15 +2190,17 @@ njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_DECLINED; case NJS_TOKEN_GRAVE: - njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_create_call(parser, parser->node, 0); if (node == NULL) { return NJS_ERROR; } + node->token_line = token->line; + parser->node = node; + njs_lexer_consume_token(parser->lexer, 1); + njs_parser_next(parser, njs_parser_template_literal); break; @@ -2437,18 +2476,20 @@ njs_parser_member_expression_new_after(njs_parser_t *parser, return NJS_ERROR; } + parser->node->token_line = token->line; + return njs_parser_stack_pop(parser); } - njs_lexer_consume_token(parser->lexer, 1); - func = njs_parser_create_call(parser, parser->node, 1); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_arguments); return njs_parser_after(parser, current, func, 1, @@ -2562,15 +2603,15 @@ njs_parser_call_expression_args(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_failed(parser); } - njs_lexer_consume_token(parser->lexer, 1); - func = njs_parser_create_call(parser, parser->node, 0); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_arguments); return njs_parser_after(parser, current, func, 1, @@ -2594,15 +2635,15 @@ njs_parser_call_expression_after(njs_parser_t *parser, switch (token->type) { case NJS_TOKEN_OPEN_PARENTHESIS: - njs_lexer_consume_token(parser->lexer, 1); - func = njs_parser_create_call(parser, parser->node, 0); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_arguments); ret = njs_parser_after(parser, current, func, 1, @@ -2730,9 +2771,10 @@ njs_parser_argument_list_after(njs_parser_t *parser, njs_lexer_token_t *token, node->index = parser->target->index + sizeof(njs_value_t); } + node->token_line = token->line; node->left = parser->node; - parser->node->dest = node; + parser->node->dest = node; parser->target->right = node; parser->node = node; @@ -2819,15 +2861,15 @@ njs_parser_optional_chain(njs_parser_t *parser, njs_lexer_token_t *token, switch (token->type) { case NJS_TOKEN_OPEN_PARENTHESIS: - njs_lexer_consume_token(parser->lexer, 2); - func = njs_parser_create_call(parser, parser->node, 0); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 2); njs_parser_next(parser, njs_parser_arguments); ret = njs_parser_after(parser, current, func, 1, @@ -2878,15 +2920,15 @@ njs_parser_optional_chain_after(njs_parser_t *parser, njs_lexer_token_t *token, switch (token->type) { case NJS_TOKEN_OPEN_PARENTHESIS: - njs_lexer_consume_token(parser->lexer, 1); - func = njs_parser_create_call(parser, parser->node, 0); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_arguments); ret = njs_parser_after(parser, current, func, 1, @@ -2957,6 +2999,7 @@ njs_parser_new_expression_after(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + func->token_line = token->line; parser->node = func; return njs_parser_stack_pop(parser); @@ -3028,15 +3071,15 @@ njs_parser_left_hand_side_expression_after(njs_parser_t *parser, switch (token->type) { /* CallExpression */ case NJS_TOKEN_OPEN_PARENTHESIS: - njs_lexer_consume_token(parser->lexer, 1); - func = njs_parser_create_call(parser, parser->node, 0); if (func == NULL) { return NJS_ERROR; } + func->token_line = token->line; parser->node = func; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_arguments); ret = njs_parser_after(parser, current, func, 1, @@ -3108,17 +3151,18 @@ njs_parser_expression_node(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_stack_pop(parser); } - njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_node_new(parser, type); if (node == NULL) { return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; + njs_lexer_consume_token(parser->lexer, 1); + return njs_parser_after(parser, current, node, 0, after); } @@ -3154,6 +3198,7 @@ njs_parser_update_expression(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; njs_lexer_consume_token(parser->lexer, 1); @@ -3193,9 +3238,9 @@ njs_parser_update_expression_post(njs_parser_t *parser, return njs_parser_stack_pop(parser); } - njs_lexer_consume_token(parser->lexer, 1); - if (!njs_parser_is_lvalue(parser->node)) { + njs_lexer_consume_token(parser->lexer, 1); + njs_parser_ref_error(parser, "Invalid left-hand side in postfix operation"); return NJS_DONE; @@ -3206,10 +3251,14 @@ njs_parser_update_expression_post(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; + parser->node = node; + njs_lexer_consume_token(parser->lexer, 1); + return njs_parser_stack_pop(parser); } @@ -3293,17 +3342,18 @@ njs_parser_unary_expression(njs_parser_t *parser, njs_lexer_token_t *token, njs_parser_unary_expression_after); } - njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_node_new(parser, type); if (node == NULL) { return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; parser->target = node; + njs_lexer_consume_token(parser->lexer, 1); + return njs_parser_after(parser, current, node, 0, njs_parser_unary_expression_next); } @@ -3435,6 +3485,7 @@ njs_parser_exponentiation_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = NJS_VMCODE_EXPONENTIATION; node->left = parser->node; node->left->dest = node; @@ -3501,6 +3552,7 @@ njs_parser_multiplicative_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; @@ -3563,6 +3615,7 @@ njs_parser_additive_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; @@ -3629,6 +3682,7 @@ njs_parser_shift_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; @@ -3707,6 +3761,7 @@ njs_parser_relational_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; @@ -3777,6 +3832,7 @@ njs_parser_equality_expression_match(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; node->left->dest = node; @@ -3947,17 +4003,17 @@ njs_parser_coalesce_expression(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_failed(parser); } - njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_node_new(parser, NJS_TOKEN_COALESCE); if (node == NULL) { return NJS_ERROR; } + node->token_line = token->line; node->u.operation = NJS_VMCODE_COALESCE; node->left = parser->node; node->left->dest = node; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_bitwise_OR_expression); return njs_parser_after(parser, current, node, 0, @@ -4000,13 +4056,12 @@ njs_parser_conditional_question_mark(njs_parser_t *parser, return njs_parser_stack_pop(parser); } - njs_lexer_consume_token(parser->lexer, 1); - cond = njs_parser_node_new(parser, NJS_TOKEN_CONDITIONAL); if (cond == NULL) { return NJS_ERROR; } + cond->token_line = token->line; cond->left = parser->node; node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING); @@ -4014,8 +4069,10 @@ njs_parser_conditional_question_mark(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = token->line; cond->right = node; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_assignment_expression); return njs_parser_after(parser, current, cond, 1, @@ -4277,6 +4334,7 @@ njs_parser_assignment_operator(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = token->line; node->u.operation = operation; node->left = parser->node; @@ -4358,16 +4416,18 @@ njs_parser_statement(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_stack_pop(parser); case NJS_TOKEN_EXPORT: - njs_lexer_consume_token(parser->lexer, 1); + parser->line = token->line; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_export); return njs_parser_after(parser, current, parser->node, 1, njs_parser_statement_after); case NJS_TOKEN_IMPORT: - njs_lexer_consume_token(parser->lexer, 1); + parser->line = token->line; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_import); return njs_parser_after(parser, current, parser->node, 1, @@ -4425,12 +4485,10 @@ njs_parser_statement_wo_node(njs_parser_t *parser, njs_lexer_token_t *token, break; case NJS_TOKEN_CONTINUE: - parser->line = token->line; njs_parser_next(parser, njs_parser_continue_statement); break; case NJS_TOKEN_BREAK: - parser->line = token->line; njs_parser_next(parser, njs_parser_break_statement); break; @@ -4474,6 +4532,8 @@ njs_parser_statement_wo_node(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_OK; } + parser->line = token->line; + njs_lexer_consume_token(parser->lexer, 1); return NJS_OK; @@ -4577,6 +4637,7 @@ static njs_int_t njs_parser_block_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { + void *target; njs_int_t ret; ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK); @@ -4584,16 +4645,19 @@ njs_parser_block_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + target = (void *) (uintptr_t) parser->line; parser->node = NULL; if (token->type == NJS_TOKEN_CLOSE_BRACE) { + parser->target = target; + njs_parser_next(parser, njs_parser_block_statement_close_brace); return NJS_OK; } njs_parser_next(parser, njs_parser_statement_list); - return njs_parser_after(parser, current, NULL, 1, + return njs_parser_after(parser, current, target, 1, njs_parser_block_statement_close_brace); } @@ -4606,6 +4670,8 @@ njs_parser_block_statement_open_brace(njs_parser_t *parser, return njs_parser_failed(parser); } + parser->line = token->line; + njs_lexer_consume_token(parser->lexer, 1); token = njs_lexer_token(parser->lexer, 0); @@ -4632,8 +4698,11 @@ njs_parser_block_statement_close_brace(njs_parser_t *parser, return NJS_ERROR; } + node->token_line = (uint32_t) (uintptr_t) parser->target; node->left = parser->node; node->right = NULL; + + parser->target = NULL; parser->node = node; njs_parser_scope_end(parser); @@ -4766,6 +4835,8 @@ njs_parser_variable_declaration(njs_parser_t *parser, return NJS_ERROR; } + name->token_line = token->line; + parser->node = name; njs_lexer_consume_token(parser->lexer, 1); @@ -4776,11 +4847,16 @@ njs_parser_variable_declaration(njs_parser_t *parser, } ret = njs_parser_initializer_assign(parser, NJS_TOKEN_VAR); + if (ret != NJS_OK) { + return ret; + } + + parser->node->token_line = token->line; if (token->type == NJS_TOKEN_ASSIGNMENT) { njs_parser_next(parser, njs_parser_initializer); - return ret; + return NJS_OK; } parser->target = parser->node; @@ -4788,7 +4864,7 @@ njs_parser_variable_declaration(njs_parser_t *parser, njs_parser_next(parser, njs_parser_initializer_after); - return ret; + return NJS_OK; } @@ -4923,6 +4999,8 @@ njs_parser_if_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = parser->line; + parser->node = NULL; njs_parser_next(parser, njs_parser_expression); @@ -4965,12 +5043,23 @@ static njs_int_t njs_parser_else_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { + njs_parser_node_t *node; + parser->target->right = parser->node; parser->node = NULL; if (token->type == NJS_TOKEN_ELSE) { - njs_lexer_consume_token(parser->lexer, 1); + node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + node->left = parser->target->right; + parser->target->right = node; + + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_statement_wo_node); return njs_parser_after(parser, current, parser->target, 1, @@ -4987,17 +5076,7 @@ static njs_int_t njs_parser_else_statement_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - - node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING); - if (node == NULL) { - return NJS_ERROR; - } - - node->left = parser->target->right; - node->right = parser->node; - - parser->target->right = node; + parser->target->right->right = parser->node; parser->node = parser->target; @@ -5009,11 +5088,20 @@ static njs_int_t njs_parser_iteration_statement_do(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { + njs_parser_node_t *node; + + node = njs_parser_node_new(parser, NJS_TOKEN_DO); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = parser->line; + parser->node = NULL; njs_parser_next(parser, njs_parser_statement_wo_node); - return njs_parser_after(parser, current, NULL, 1, + return njs_parser_after(parser, current, node, 1, njs_parser_iteration_statement_do_while); } @@ -5026,11 +5114,13 @@ njs_parser_iteration_statement_do_while(njs_parser_t *parser, return njs_parser_failed(parser); } + parser->target->left = parser->node; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_expression_parenthesis); - return njs_parser_after(parser, current, parser->node, 1, + return njs_parser_after(parser, current, parser->target, 1, njs_parser_do_while_semicolon); } @@ -5039,20 +5129,12 @@ static njs_int_t njs_parser_do_while_semicolon(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - if (parser->strict_semicolon) { return njs_parser_failed(parser); } - node = njs_parser_node_new(parser, NJS_TOKEN_DO); - if (node == NULL) { - return NJS_ERROR; - } - - node->left = parser->target; - node->right = parser->node; - parser->node = node; + parser->target->right = parser->node; + parser->node = parser->target; return njs_parser_stack_pop(parser); } @@ -5062,9 +5144,18 @@ static njs_int_t njs_parser_iteration_statement_while(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { + njs_parser_node_t *node; + + node = njs_parser_node_new(parser, NJS_TOKEN_WHILE); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + njs_parser_next(parser, njs_parser_expression_parenthesis); - return njs_parser_after(parser, current, NULL, 1, + return njs_parser_after(parser, current, node, 1, njs_parser_while_statement); } @@ -5073,15 +5164,13 @@ static njs_int_t njs_parser_while_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - - node = parser->node; - + parser->target->right = parser->node; parser->node = NULL; njs_parser_next(parser, njs_parser_statement_wo_node); - return njs_parser_after(parser, current, node, 1, njs_parser_while_after); + return njs_parser_after(parser, current, parser->target, 1, + njs_parser_while_after); } @@ -5089,16 +5178,8 @@ static njs_int_t njs_parser_while_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - - node = njs_parser_node_new(parser, NJS_TOKEN_WHILE); - if (node == NULL) { - return NJS_ERROR; - } - - node->left = parser->node; - node->right = parser->target; - parser->node = node; + parser->target->left = parser->node; + parser->node = parser->target; return njs_parser_stack_pop(parser); } @@ -5113,7 +5194,9 @@ njs_parser_iteration_statement_for(njs_parser_t *parser, njs_parser_next(parser, njs_parser_iteration_statement_for_map); - return NJS_OK; + return njs_parser_after(parser, current, + (void *) (uintptr_t) parser->line, 1, + njs_parser_set_line_state); } if (token->type == NJS_TOKEN_AWAIT) { @@ -5226,7 +5309,7 @@ njs_parser_for_var_binding_or_var_list(njs_parser_t *parser, { njs_int_t ret; njs_lexer_token_t *next; - njs_parser_node_t *node; + njs_parser_node_t *node, *var; switch (token->type) { /* BindingPattern */ @@ -5256,14 +5339,24 @@ njs_parser_for_var_binding_or_var_list(njs_parser_t *parser, return NJS_OK; } - node = njs_parser_variable_node(parser, token->unique_id, + var = njs_parser_variable_node(parser, token->unique_id, NJS_VARIABLE_VAR); - if (node == NULL) { + if (var == NULL) { return NJS_ERROR; } + var->token_line = token->line; + parser->node = NULL; + node = njs_parser_node_new(parser, NJS_TOKEN_IN); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = next->line; + node->left = var; + njs_parser_next(parser, njs_parser_expression); ret = njs_parser_after(parser, current, node, 1, @@ -5289,27 +5382,18 @@ static njs_int_t njs_parser_for_var_in_statement(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) { return njs_parser_failed(parser); } njs_lexer_consume_token(parser->lexer, 1); - node = njs_parser_node_new(parser, NJS_TOKEN_IN); - if (node == NULL) { - return NJS_ERROR; - } - - node->left = parser->target; - node->right = parser->node; - + parser->target->right = parser->node; parser->node = NULL; njs_parser_next(parser, njs_parser_statement_wo_node); - return njs_parser_after(parser, current, node, 1, + return njs_parser_after(parser, current, parser->target, 1, njs_parser_for_var_in_statement_after); } @@ -5658,6 +5742,8 @@ njs_parser_return_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = parser->line; + switch (token->type) { case NJS_TOKEN_SEMICOLON: break; @@ -5734,6 +5820,8 @@ njs_parser_switch_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + swtch->token_line = parser->line; + njs_parser_next(parser, njs_parser_expression_parenthesis); ret = njs_parser_after(parser, current, swtch, 1, @@ -5811,6 +5899,7 @@ njs_parser_switch_case_def(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + branch->token_line = token->line; branch->right = node; njs_parser_next(parser, njs_parser_expression); @@ -5840,8 +5929,6 @@ njs_parser_switch_case_def(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_DONE; } - njs_lexer_consume_token(parser->lexer, 1); - if (parser->target->token_type == NJS_TOKEN_SWITCH) { parser->target->right = node; @@ -5849,10 +5936,12 @@ njs_parser_switch_case_def(njs_parser_t *parser, njs_lexer_token_t *token, parser->target->left = node; } + node->token_line = token->line; node->token_type = NJS_TOKEN_DEFAULT; parser->target = node; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_switch_case_after_wo_def); break; @@ -6061,6 +6150,8 @@ njs_parser_throw_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = parser->line; + if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) { njs_parser_syntax_error(parser, "Illegal newline after throw"); return NJS_DONE; @@ -6109,6 +6200,8 @@ njs_parser_try_statement(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + try->token_line = parser->line; + parser->node = NULL; njs_parser_next(parser, njs_parser_block_statement_open_brace); @@ -6130,10 +6223,21 @@ njs_parser_catch_or_finally(njs_parser_t *parser, njs_lexer_token_t *token, try->left = parser->node; if (token->type == NJS_TOKEN_FINALLY) { - njs_lexer_consume_token(parser->lexer, 1); + node = njs_parser_node_new(parser, NJS_TOKEN_FINALLY); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + + if (try->right != NULL) { + node->left = try->right; + } + try->right = node; parser->node = NULL; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_block_statement_open_brace); return njs_parser_after(parser, current, try, 0, @@ -6144,13 +6248,15 @@ njs_parser_catch_or_finally(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_DONE; } - njs_lexer_consume_token(parser->lexer, 1); - catch = njs_parser_node_new(parser, NJS_TOKEN_CATCH); if (catch == NULL) { return NJS_ERROR; } + catch->token_line = token->line; + + njs_lexer_consume_token(parser->lexer, 1); + token = njs_lexer_token(parser->lexer, 0); if (token == NULL) { return NJS_ERROR; @@ -6194,6 +6300,8 @@ njs_parser_catch_or_finally(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = token->line; + catch->left = node; njs_lexer_consume_token(parser->lexer, 1); @@ -6220,15 +6328,28 @@ static njs_int_t njs_parser_catch_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { + njs_parser_node_t *node; + njs_parser_scope_end(parser); parser->target->right->right = parser->node; if (token->type == NJS_TOKEN_FINALLY) { - njs_lexer_consume_token(parser->lexer, 1); + node = njs_parser_node_new(parser, NJS_TOKEN_FINALLY); + if (node == NULL) { + return NJS_ERROR; + } + + node->token_line = token->line; + + if (parser->target->right != NULL) { + node->left = parser->target->right; + } + parser->target->right = node; parser->node = NULL; + njs_lexer_consume_token(parser->lexer, 1); njs_parser_next(parser, njs_parser_block_statement_open_brace); return njs_parser_after(parser, current, parser->target, 1, @@ -6265,24 +6386,11 @@ static njs_int_t njs_parser_catch_finally(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *node; - if (parser->ret != NJS_OK) { return njs_parser_failed(parser); } - node = njs_parser_node_new(parser, NJS_TOKEN_FINALLY); - if (node == NULL) { - return NJS_ERROR; - } - - node->right = parser->node; - - if (parser->target->right != NULL) { - node->left = parser->target->right; - } - - parser->target->right = node; + parser->target->right->right = parser->node; parser->node = parser->target; return njs_parser_stack_pop(parser); @@ -7115,8 +7223,6 @@ njs_parser_function_lambda_body_after(njs_parser_t *parser, return njs_parser_failed(parser); } - njs_lexer_consume_token(parser->lexer, 1); - parent = parser->target; last = NULL; @@ -7144,6 +7250,8 @@ njs_parser_function_lambda_body_after(njs_parser_t *parser, if (body == NULL) { return NJS_ERROR; } + + body->right->token_line = token->line; } parent->right = body; @@ -7151,6 +7259,8 @@ njs_parser_function_lambda_body_after(njs_parser_t *parser, njs_parser_scope_end(parser); + njs_lexer_consume_token(parser->lexer, 1); + return njs_parser_stack_pop(parser); } @@ -7178,6 +7288,7 @@ njs_parser_export(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + node->token_line = parser->line; parser->node = node; njs_parser_next(parser, njs_parser_expression); @@ -7201,7 +7312,7 @@ static njs_int_t njs_parser_import(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *name; + njs_parser_node_t *name, *import; if (parser->scope->type != NJS_SCOPE_GLOBAL && !parser->scope->module) { njs_parser_syntax_error(parser, "Illegal import statement"); @@ -7218,6 +7329,8 @@ njs_parser_import(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } + name->token_line = token->line; + njs_lexer_consume_token(parser->lexer, 1); token = njs_lexer_token(parser->lexer, 0); @@ -7240,9 +7353,18 @@ njs_parser_import(njs_parser_t *parser, njs_lexer_token_t *token, return njs_parser_failed(parser); } + import = njs_parser_node_new(parser, NJS_TOKEN_IMPORT); + if (import == NULL) { + return NJS_ERROR; + } + + import->token_line = parser->line; + import->left = name; + njs_parser_next(parser, njs_parser_module); - return njs_parser_after(parser, current, name, 1, njs_parser_import_after); + return njs_parser_after(parser, current, import, 1, + njs_parser_import_after); } @@ -7250,21 +7372,13 @@ static njs_int_t njs_parser_import_after(njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current) { - njs_parser_node_t *import; - if (njs_parser_expect_semicolon(parser, token) != NJS_OK) { return njs_parser_failed(parser); } - import = njs_parser_node_new(parser, NJS_TOKEN_IMPORT); - if (import == NULL) { - return NJS_ERROR; - } - - import->left = parser->target; - import->right = parser->node; + parser->target->right = parser->node; - parser->node = import; + parser->node = parser->target; parser->node->hoist = 1; return njs_parser_stack_pop(parser); @@ -7284,14 +7398,14 @@ njs_parser_module_lambda(njs_parser_t *parser, njs_lexer_token_t *token, return NJS_ERROR; } - node->token_line = token->line; - lambda = njs_function_lambda_alloc(parser->vm, 1); if (lambda == NULL) { return NJS_ERROR; } + node->token_line = token->line; node->u.value.data.u.lambda = lambda; + parser->node = node; ret = njs_parser_scope_begin(parser, NJS_SCOPE_FUNCTION); @@ -7323,7 +7437,6 @@ njs_parser_module_lambda_after(njs_parser_t *parser, njs_lexer_token_t *token, } parser->target->right = njs_parser_chain_top(parser); - parser->target->right->token_line = 1; parser->node = parser->target; @@ -7397,6 +7510,10 @@ njs_parser_return_set(njs_parser_t *parser, njs_parser_node_t *expr) return NULL; } + if (expr != NULL) { + node->token_line = expr->token_line; + } + node->right = expr; stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT); @@ -7486,7 +7603,6 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) } else { node->token_type = NJS_TOKEN_NON_LOCAL_THIS; - node->token_line = token->line; ret = njs_variable_reference(parser->vm, scope, node, @@ -7581,6 +7697,7 @@ njs_parser_argument(njs_parser_t *parser, njs_parser_node_t *expr, return NULL; } + node->token_line = expr->token_line; node->index = index; node->left = expr; @@ -7603,6 +7720,7 @@ njs_parser_object_property(njs_parser_t *parser, njs_parser_node_t *parent, return NJS_TOKEN_ERROR; } + object->token_line = value->token_line; object->u.object = parent; type = proto_init ? NJS_TOKEN_PROTO_INIT : NJS_TOKEN_PROPERTY_INIT; @@ -7612,6 +7730,7 @@ njs_parser_object_property(njs_parser_t *parser, njs_parser_node_t *parent, return NJS_ERROR; } + propref->token_line = value->token_line; propref->left = object; propref->right = property; @@ -7620,6 +7739,7 @@ njs_parser_object_property(njs_parser_t *parser, njs_parser_node_t *parent, return NJS_ERROR; } + assign->token_line = value->token_line; assign->u.operation = NJS_VMCODE_MOVE; assign->left = propref; assign->right = value; @@ -7649,6 +7769,7 @@ njs_parser_property_accessor(njs_parser_t *parser, njs_parser_node_t *parent, return NJS_TOKEN_ERROR; } + object->token_line = value->token_line; object->u.object = parent; propref = njs_parser_node_new(parser, 0); @@ -7664,6 +7785,7 @@ njs_parser_property_accessor(njs_parser_t *parser, njs_parser_node_t *parent, return NJS_ERROR; } + node->token_line = value->token_line; node->left = propref; node->right = value; @@ -7694,6 +7816,8 @@ njs_parser_array_item(njs_parser_t *parser, njs_parser_node_t *array, njs_set_number(&number->u.value, array->u.length); + number->token_line = value->token_line; + ret = njs_parser_object_property(parser, array, number, value, 0); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -7764,6 +7888,8 @@ done: return NJS_ERROR; } + node->token_line = token->line; + if (escape) { ret = njs_parser_escape_string_create(parser, token, &node->u.value); if (njs_slow_path(ret != NJS_TOKEN_STRING)) { @@ -8350,7 +8476,9 @@ njs_parser_serialize_tree(njs_chb_t *chain, njs_parser_node_t *node, *ret |= njs_parser_serialize_node(chain, node); - njs_chb_append_literal(chain, "\""); + njs_chb_append_literal(chain, "\",\n"); + njs_parser_serialize_indent(chain, indent); + njs_chb_sprintf(chain, 32, " \"line\": %d", node->token_line); switch (node->token_type) { case NJS_TOKEN_NUMBER: diff --git a/src/njs_parser.h b/src/njs_parser.h index e42e5364..72e75f8c 100644 --- a/src/njs_parser.h +++ b/src/njs_parser.h @@ -194,6 +194,8 @@ njs_parser_node_string(njs_vm_t *vm, njs_lexer_token_t *token, return NULL; } + node->token_line = token->line; + return node; } -- 2.47.3