示例#1
0
njs_token_t
njs_parser_token(njs_parser_t *parser)
{
    njs_token_t  token;

    do {
        token = njs_lexer_token(parser->lexer);

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

    } while (nxt_slow_path(token == NJS_TOKEN_LINE_END));

    return token;
}
示例#2
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;
            }
        }
    }
}
示例#3
0
static njs_token_t
njs_parser_binary_expression(njs_vm_t *vm, njs_parser_t *parser,
    const njs_parser_expression_t *expr, njs_token_t token)
{
    nxt_int_t                     n;
    njs_parser_node_t             *node;
    const njs_parser_operation_t  *op;

    token = expr->next(vm, parser, expr->expression, token);
    if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
        return token;
    }

    for ( ;; ) {
        n = expr->count;
        op = expr->op;

        do {
            if (op->token == token) {
                goto found;
            }

            op++;
            n--;

        } while (n != 0);

        if (token == 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;
            }
        }

        return token;

    found:

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

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

        parser->code_size += op->size;

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

        token = expr->next(vm, parser, expr->expression, token);
        if (nxt_slow_path(token <= NJS_TOKEN_ILLEGAL)) {
            return token;
        }

        node->right = parser->node;
        node->right->dest = node;
        parser->node = node;
    }
}
示例#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;
            }
        }
    }
}