示例#1
0
static njs_token_t
njs_parser_inc_dec_expression(njs_vm_t *vm, njs_parser_t *parser,
    njs_token_t token)
{
    njs_token_t             next;
    njs_parser_node_t       *node;
    njs_vmcode_operation_t  operation;

    switch (token) {

    case NJS_TOKEN_INCREMENT:
        operation = njs_vmcode_increment;
        break;

    case NJS_TOKEN_DECREMENT:
        operation = njs_vmcode_decrement;
        break;

    default:
        return njs_parser_post_inc_dec_expression(vm, parser, token);
    }

    next = njs_parser_token(parser);
    if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
        return next;
    }

    next = njs_parser_call_expression(vm, parser, next);
    if (nxt_slow_path(next <= NJS_TOKEN_ILLEGAL)) {
        return next;
    }

    if (parser->node->lvalue == NJS_LVALUE_NONE) {
        nxt_thread_log_error(NXT_LOG_ALERT, "lvalue required");
        return NJS_TOKEN_ILLEGAL;
    }

    node = njs_parser_node_alloc(vm);
    if (nxt_slow_path(node == NULL)) {
        return NJS_TOKEN_ERROR;
    }

    node->token = token;
    node->u.operation = operation;
    node->left = parser->node;
    parser->node = node;

    parser->code_size += (parser->node->token == NJS_TOKEN_NAME) ?
                             sizeof(njs_vmcode_3addr_t):
                             sizeof(njs_vmcode_prop_get_t)
                             + sizeof(njs_vmcode_3addr_t)
                             + sizeof(njs_vmcode_prop_set_t);

    return next;
}
示例#2
0
njs_parser_node_t *
njs_nonrecursive_parser(njs_vm_t *vm, njs_parser_t *parser)
{
    nxt_int_t                     ret;
    njs_token_t                   token;
    njs_parser_stack_operation_t  operation;

    if (top < 0) {
        njs_parser_stack_push(vm, parser, njs_parser_statement);
    }

    token = njs_parser_token(parser);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        /* TODO: NJS_TOKEN_AGAIN */
        return NULL;
    }

    do {
        operation = (njs_parser_stack_operation_t) njs_parser_stack_pop(parser);

        if (operation == NULL) {

            if (parser->lexer->token == NJS_TOKEN_END) {
                return parser->node;
            }

            break;
        }

        ret = operation(vm, parser, njs_parser_stack_pop(parser));

    } while (ret == NXT_OK);

    nxt_thread_log_error(NXT_LOG_ERR, "unexpected token");

    return NULL;
}
示例#3
0
static njs_token_t
njs_parser_assignment_expression(njs_vm_t *vm, njs_parser_t *parser,
    const njs_parser_expression_t *expr, njs_token_t token)
{
    size_t                  size;
    njs_parser_node_t       *node, *pending;
    njs_vmcode_operation_t  operation;

    token = njs_parser_conditional_expression(vm, parser, token);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        return token;
    }

    for ( ;; ) {
        switch (token) {

        case NJS_TOKEN_ASSIGNMENT:
            nxt_thread_log_debug("JS: =");
            operation = njs_vmcode_move;
            break;

        case NJS_TOKEN_ADDITION_ASSIGNMENT:
            nxt_thread_log_debug("JS: +=");
            operation = njs_vmcode_addition;
            break;

        case NJS_TOKEN_SUBSTRACTION_ASSIGNMENT:
            nxt_thread_log_debug("JS: -=");
            operation = njs_vmcode_substraction;
            break;

        case NJS_TOKEN_MULTIPLICATION_ASSIGNMENT:
            nxt_thread_log_debug("JS: *=");
            operation = njs_vmcode_multiplication;
            break;

        case NJS_TOKEN_DIVISION_ASSIGNMENT:
            nxt_thread_log_debug("JS: /=");
            operation = njs_vmcode_division;
            break;

        case NJS_TOKEN_REMAINDER_ASSIGNMENT:
            nxt_thread_log_debug("JS: %=");
            operation = njs_vmcode_remainder;
            break;

        case NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT:
            nxt_thread_log_debug("JS: <<=");
            operation = njs_vmcode_left_shift;
            break;

        case NJS_TOKEN_RIGHT_SHIFT_ASSIGNMENT:
            nxt_thread_log_debug("JS: >>=");
            operation = njs_vmcode_right_shift;
            break;

        case NJS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
            nxt_thread_log_debug("JS: >>=");
            operation = njs_vmcode_unsigned_right_shift;
            break;

        case NJS_TOKEN_BITWISE_AND_ASSIGNMENT:
            nxt_thread_log_debug("JS: &=");
            operation = njs_vmcode_bitwise_and;
            break;

        case NJS_TOKEN_BITWISE_XOR_ASSIGNMENT:
            nxt_thread_log_debug("JS: ^=");
            operation = njs_vmcode_bitwise_xor;
            break;

        case NJS_TOKEN_BITWISE_OR_ASSIGNMENT:
            nxt_thread_log_debug("JS: |=");
            operation = njs_vmcode_bitwise_or;
            break;

        case NJS_TOKEN_LINE_END:
            token = njs_lexer_token(parser->lexer);
            if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
                return token;
            }

            if (njs_parser_expression_operator(token)) {
                continue;
            }

            /* Fall through. */

        default:
            return token;
        }

        node = parser->node;

        if (node->lvalue == NJS_LVALUE_NONE) {
            nxt_thread_log_error(NXT_LOG_ALERT, "lvalue required");
            return NJS_TOKEN_ILLEGAL;
        }

        pending = NULL;

        if (node->token == NJS_TOKEN_NAME) {

            if (token == NJS_TOKEN_ASSIGNMENT) {
                node->state = NJS_VARIABLE_ASSIGNMENT;

                if (node->u.variable->state == NJS_VARIABLE_PENDING) {
                    pending = node;
                }

            } else if (node->u.variable->state == NJS_VARIABLE_PENDING) {
                node->u.variable->state = NJS_VARIABLE_USED;
            }
        }

        node = njs_parser_node_alloc(vm);
        if (nxt_slow_path(node == NULL)) {
            return NJS_TOKEN_ERROR;
        }

        node->token = token;
        node->u.operation = operation;
        node->left = parser->node;

        token = njs_parser_token(parser);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        token = njs_parser_assignment_expression(vm, parser, NULL, token);

        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        node->right = parser->node;
        parser->node = node;

        if (node->left->token == NJS_TOKEN_NAME) {

            if (node->token == NJS_TOKEN_ASSIGNMENT) {
                size = sizeof(njs_vmcode_move_t);

            } else {
                if (njs_parser_has_side_effect(node->right)) {
                    size = sizeof(njs_vmcode_move_t)
                           + sizeof(njs_vmcode_3addr_t);
                } else {
                    size = sizeof(njs_vmcode_3addr_t);
                }
            }

        } else {
            if (node->token == NJS_TOKEN_ASSIGNMENT) {
                size = sizeof(njs_vmcode_prop_set_t);

                if (njs_parser_has_side_effect(node->right)) {
                    size += 2 * sizeof(njs_vmcode_move_t);
                }

            } else {
                size = sizeof(njs_vmcode_prop_get_t)
                       + sizeof(njs_vmcode_3addr_t)
                       + sizeof(njs_vmcode_prop_set_t);
            }
        }

        parser->code_size += size;

        if (pending != NULL
            && pending->u.variable->state == NJS_VARIABLE_PENDING)
        {
            pending->u.variable->state = NJS_VARIABLE_SET;

            if (!parser->branch) {
                pending->state = NJS_VARIABLE_FIRST_ASSIGNMENT;
            }
        }
    }
}
示例#4
0
njs_token_t
njs_parser_var_expression(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
{
    size_t                  size;
    njs_parser_node_t       *node, *pending;
    njs_vmcode_operation_t  operation;

    token = njs_parser_conditional_expression(vm, parser, token);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        return token;
    }

    for ( ;; ) {
        size = sizeof(njs_vmcode_3addr_t);

        switch (token) {

        case NJS_TOKEN_ASSIGNMENT:
            nxt_thread_log_debug("JS: =");
            operation = njs_vmcode_move;
            size = sizeof(njs_vmcode_move_t);
            break;

        case NJS_TOKEN_LINE_END:
            token = njs_lexer_token(parser->lexer);
            if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
                return token;
            }

            if (njs_parser_expression_operator(token)) {
                continue;
            }

            /* Fall through. */

        default:
            return token;
        }

        node = parser->node;

        if (node->lvalue == NJS_LVALUE_NONE) {
            nxt_thread_log_error(NXT_LOG_ALERT, "lvalue required");
            return NJS_TOKEN_ILLEGAL;
        }

        pending = NULL;

        if (node->token == NJS_TOKEN_NAME) {
            node->state = NJS_VARIABLE_ASSIGNMENT;

            if (node->u.variable->state == NJS_VARIABLE_PENDING) {
                pending = node;
            }
        }

        node = njs_parser_node_alloc(vm);
        if (nxt_slow_path(node == NULL)) {
            return NJS_TOKEN_ERROR;
        }

        node->token = token;
        node->u.operation = operation;
        node->left = parser->node;
        parser->code_size += size;

        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;
        }

        node->right = parser->node;
        parser->node = node;

        if (pending != NULL
            && pending->u.variable->state == NJS_VARIABLE_PENDING)
        {
            pending->u.variable->state = NJS_VARIABLE_SET;
            parser->code_size -= sizeof(njs_vmcode_1addr_t);

            if (!parser->branch) {
                pending->state = NJS_VARIABLE_FIRST_ASSIGNMENT;
            }
        }
    }
}