⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsparse.c

📁 一个基于alice开发的机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
                                      SPROP_INVALID_SLOT,
                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |
                                      JSPROP_SHARED,
                                      SPROP_HAS_SHORTID | dupflag,
                                      fun->nargs)) {
                return NULL;
            }
            fun->nargs++;
        } while (js_MatchToken(cx, ts, TOK_COMMA));

        MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL);
    }

    MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
    pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;

    TREE_CONTEXT_INIT(&funtc);
    body = FunctionBody(cx, ts, fun, &funtc);
    if (!body)
        return NULL;

    MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
    pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;

#if JS_HAS_LEXICAL_CLOSURE
    /*
     * If we collected flags that indicate nested heavyweight functions, or
     * this function contains heavyweight-making statements (references to
     * __parent__ or __proto__; use of with, eval, import, or export; and
     * assignment to arguments), flag the function as heavyweight (requiring
     * a call object per invocation).
     */
    if (funtc.flags & TCF_FUN_HEAVYWEIGHT) {
        fun->flags |= JSFUN_HEAVYWEIGHT;
        tc->flags |= TCF_FUN_HEAVYWEIGHT;
    } else {
        /*
         * If this function is a named statement function not at top-level
         * (i.e. a JSOP_CLOSURE), or if it refers to unqualified names that
         * are not local args or vars (TCF_FUN_USES_NONLOCALS), then our
         * enclosing function, if any, must be heavyweight.
         */
        if ((!lambda && funAtom && tc->topStmt) ||
            (funtc.flags & TCF_FUN_USES_NONLOCALS)) {
            tc->flags |= TCF_FUN_HEAVYWEIGHT;
        }
    }
#endif

    /*
     * Record names for function statements in tc->decls so we know when to
     * avoid optimizing variable references that might name a function.
     */
    if (!lambda && funAtom) {
        ATOM_LIST_SEARCH(ale, &tc->decls, funAtom);
        if (ale) {
            prevop = ALE_JSOP(ale);
            if (JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) {
                const char *name = js_AtomToPrintableString(cx, funAtom);
                if (!name ||
                    !js_ReportCompileErrorNumber(cx, ts, NULL,
                                                 (prevop != JSOP_DEFCONST)
                                                 ? JSREPORT_WARNING |
                                                   JSREPORT_STRICT
                                                 : JSREPORT_ERROR,
                                                 JSMSG_REDECLARED_VAR,
                                                 (prevop == JSOP_DEFFUN ||
                                                  prevop == JSOP_CLOSURE)
                                                 ? js_function_str
                                                 : (prevop == JSOP_DEFCONST)
                                                 ? js_const_str
                                                 : js_var_str,
                                                 name)) {
                    return NULL;
                }
            }
            if (tc->topStmt && prevop == JSOP_DEFVAR)
                tc->flags |= TCF_FUN_CLOSURE_VS_VAR;
        } else {
            ale = js_IndexAtom(cx, funAtom, &tc->decls);
            if (!ale)
                return NULL;
        }
        ALE_SET_JSOP(ale, tc->topStmt ? JSOP_CLOSURE : JSOP_DEFFUN);

#if JS_HAS_LEXICAL_CLOSURE
        /*
         * A function nested at top level inside another's body needs only a
         * local variable to bind its name to its value, and not an activation
         * object property (it might also need the activation property, if the
         * outer function contains with statements, e.g., but the stack slot
         * wins when jsemit.c's LookupArgOrVar can optimize a JSOP_NAME into a
         * JSOP_GETVAR bytecode).
         */
        if (!tc->topStmt && (tc->flags & TCF_IN_FUNCTION)) {
            JSStackFrame *fp;
            JSObject *varobj;

            /*
             * Define a property on the outer function so that LookupArgOrVar
             * can properly optimize accesses.
             *
             * XXX Here and in Variables, we use the function object's scope,
             * XXX arguably polluting it, when we could use a compiler-private
             * XXX scope structure.  Tradition!
             */
            fp = cx->fp;
            varobj = fp->varobj;
            JS_ASSERT(OBJ_GET_CLASS(cx, varobj) == &js_FunctionClass);
            JS_ASSERT(fp->fun == (JSFunction *) JS_GetPrivate(cx, varobj));
            if (!js_DefineNativeProperty(cx, varobj, (jsid)funAtom,
                                         OBJECT_TO_JSVAL(fun->object),
                                         js_GetLocalVariable,
                                         js_SetLocalVariable,
                                         JSPROP_ENUMERATE,
                                         SPROP_HAS_SHORTID, fp->fun->nvars,
                                         NULL)) {
                return NULL;
            }
            fp->fun->nvars++;
        }
#endif
    }

#if JS_HAS_LEXICAL_CLOSURE
    if (lambda || !funAtom) {
        /*
         * ECMA ed. 3 standard: function expression, possibly anonymous (even
         * if at top-level, an unnamed function is an expression statement, not
         * a function declaration).
         */
        op = fun->atom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ;
    } else if (tc->topStmt) {
        /*
         * ECMA ed. 3 extension: a function expression statement not at the
         * top level, e.g., in a compound statement such as the "then" part
         * of an "if" statement, binds a closure only if control reaches that
         * sub-statement.
         */
        op = JSOP_CLOSURE;
    } else
#endif
        op = JSOP_NOP;

    /*
     * Pending a better automatic GC root management scheme (see Mozilla bug
     * 40757, http://bugzilla.mozilla.org/show_bug.cgi?id=40757), we need to
     * atomize here to protect against a GC activation.
     */
    pn->pn_funAtom = js_AtomizeObject(cx, fun->object, 0);
    if (!pn->pn_funAtom)
        return NULL;

    pn->pn_op = op;
    pn->pn_body = body;
    pn->pn_flags = funtc.flags & TCF_FUN_FLAGS;
    pn->pn_tryCount = funtc.tryCount;
    TREE_CONTEXT_FINISH(&funtc);
    return pn;
}

static JSParseNode *
FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
    return FunctionDef(cx, ts, tc, JS_FALSE);
}

#if JS_HAS_LEXICAL_CLOSURE
static JSParseNode *
FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
    return FunctionDef(cx, ts, tc, JS_TRUE);
}
#endif

/*
 * Parse the statements in a block, creating a TOK_LC node that lists the
 * statements' trees.  If called from block-parsing code, the caller must
 * match { before and } after.
 */
static JSParseNode *
Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
    JSParseNode *pn, *pn2;
    JSTokenType tt;

    CHECK_RECURSION();

    pn = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_LIST, tc);
    if (!pn)
        return NULL;
    PN_INIT_LIST(pn);

    ts->flags |= TSF_REGEXP;
    while ((tt = js_PeekToken(cx, ts)) > TOK_EOF && tt != TOK_RC) {
        ts->flags &= ~TSF_REGEXP;
        pn2 = Statement(cx, ts, tc);
        if (!pn2)
            return NULL;
        ts->flags |= TSF_REGEXP;

        /* If compiling top-level statements, emit as we go to save space. */
        if (!tc->topStmt && (tc->flags & TCF_COMPILING)) {
            if (cx->fp->fun &&
                JS_HAS_STRICT_OPTION(cx) &&
                (tc->flags & TCF_RETURN_EXPR)) {
                /*
                 * Check pn2 for lack of a final return statement if it is the
                 * last statement in the block.
                 */
                tt = js_PeekToken(cx, ts);
                if ((tt == TOK_EOF || tt == TOK_RC) &&
                    !CheckFinalReturn(cx, ts, pn2)) {
                    tt = TOK_ERROR;
                    break;
                }

                /*
                 * Clear TCF_RETURN_EXPR so FunctionBody doesn't try to
                 * CheckFinalReturn again.
                 */
                tc->flags &= ~TCF_RETURN_EXPR;
            }
            if (!js_FoldConstants(cx, pn2, tc) ||
                !js_AllocTryNotes(cx, (JSCodeGenerator *)tc) ||
                !js_EmitTree(cx, (JSCodeGenerator *)tc, pn2)) {
                tt = TOK_ERROR;
                break;
            }
            RecycleTree(pn2, tc);
        } else {
            PN_APPEND(pn, pn2);
        }
    }
    ts->flags &= ~TSF_REGEXP;
    if (tt == TOK_ERROR)
        return NULL;

    pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
    return pn;
}

static JSParseNode *
Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
    JSParseNode *pn, *pn2;

    MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
    pn = Expr(cx, ts, tc);
    if (!pn)
        return NULL;
    MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);

    /*
     * Check for (a = b) and "correct" it to (a == b) iff b's operator has
     * greater precedence than ==.
     * XXX not ECMA, but documented in several books -- now a strict warning.
     */
    if (pn->pn_type == TOK_ASSIGN &&
        pn->pn_op == JSOP_NOP &&
        pn->pn_right->pn_type > TOK_EQOP)
    {
        JSBool rewrite = !JSVERSION_IS_ECMA(cx->version);
        if (!js_ReportCompileErrorNumber(cx, ts, NULL,
                                         JSREPORT_WARNING | JSREPORT_STRICT,
                                         JSMSG_EQUAL_AS_ASSIGN,
                                         rewrite
                                         ? "\nAssuming equality test"
                                         : "")) {
            return NULL;
        }
        if (rewrite) {
            pn->pn_type = TOK_EQOP;
            pn->pn_op = (JSOp)cx->jsop_eq;
            pn2 = pn->pn_left;
            switch (pn2->pn_op) {
              case JSOP_SETNAME:
                pn2->pn_op = JSOP_NAME;
                break;
              case JSOP_SETPROP:
                pn2->pn_op = JSOP_GETPROP;
                break;
              case JSOP_SETELEM:
                pn2->pn_op = JSOP_GETELEM;
                break;
              default:
                JS_ASSERT(0);
            }
        }
    }
    return pn;
}

static JSBool
MatchLabel(JSContext *cx, JSTokenStream *ts, JSParseNode *pn)
{
    JSAtom *label;
#if JS_HAS_LABEL_STATEMENT
    JSTokenType tt;

    tt = js_PeekTokenSameLine(cx, ts);
    if (tt == TOK_ERROR)
        return JS_FALSE;
    if (tt == TOK_NAME) {
        (void) js_GetToken(cx, ts);
        label = CURRENT_TOKEN(ts).t_atom;
    } else {
        label = NULL;
    }
#else
    label = NULL;
#endif
    pn->pn_atom = label;
    return JS_TRUE;
}

#if JS_HAS_EXPORT_IMPORT
static JSParseNode *
ImportExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
    JSParseNode *pn, *pn2, *pn3;
    JSTokenType tt;

    MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NO_IMPORT_NAME);
    pn = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_NAME, tc);
    if (!pn)
        return NULL;
    pn->pn_op = JSOP_NAME;
    pn->pn_atom = CURRENT_TOKEN(ts).t_atom;
    pn->pn_expr = NULL;
    pn->pn_slot = -1;
    pn->pn_attrs = 0;

    ts->flags |= TSF_REGEXP;
    while ((tt = js_GetToken(cx, ts)) == TOK_DOT || tt == TOK_LB) {
        ts->flags &= ~TSF_REGEXP;
        if (pn->pn_op == JSOP_IMPORTALL)
            goto bad_import;

        if (tt == TOK_DOT) {
            pn2 = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_NAME, tc);
            if (!pn2)
                return NULL;
            if (js_MatchToken(cx, ts, TOK_STAR)) {
                pn2->pn_op = JSOP_IMPORTALL;
                pn2->pn_atom = NULL;
            } else {
                MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT);
                pn2->pn_op = JSOP_GETPROP;
                pn2->pn_atom = CURRENT_TOKEN(ts).t_atom;
                pn2->pn_slot = -1;
                pn2->pn_attrs = 0;
            }
            pn2->pn_expr = pn;
            pn2->pn_pos.begin = pn->pn_pos.begin;
            pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
        } else {
            /* Make a TOK_LB node. */
            pn2 = NewParseNode(cx, &CURRENT_TOKEN(ts), PN_BINARY, tc);
            if (!pn2)
                return NULL;
            pn3 = Expr(cx, ts, tc);
            if (!pn3)
                return NULL;

            MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
            pn2->pn_pos.begin = pn->pn_pos.begin;
            pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;

            pn2->pn_op = JSOP_GETELEM;
            pn2->pn_left = pn;
            pn2->pn_right = pn3;
        }

        pn = pn2;
        ts->flags |= TSF_REGEXP;
    }
    ts->flags &= ~TSF_REGEXP;
    if (tt == TOK_ERROR)
        return NULL;
    js_UngetToken(ts);

    switch (pn->pn_op) {
      case JSOP_GETPROP:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -