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

📄 jsparse.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS parser. * * This is a recursive-descent parser for the JavaScript language specified by * "The JavaScript 1.5 Language Specification".  It uses lexical and semantic * feedback to disambiguate non-LL(1) structures.  It generates trees of nodes * induced by the recursive parsing (not precise syntax trees, see jsparse.h). * After tree construction, it rewrites trees to fold constants and evaluate * compile-time expressions.  Finally, it calls js_EmitTree (see jsemit.h) to * generate bytecode. * * This parser attempts no error recovery. */#include "jsstddef.h"#include <stdlib.h>#include <string.h>#include <math.h>#include "jstypes.h"#include "jsarena.h" /* Added by JSIFY */#include "jsutil.h" /* Added by JSIFY */#include "jsapi.h"#include "jsarray.h"#include "jsatom.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsemit.h"#include "jsfun.h"#include "jsinterp.h"#include "jslock.h"#include "jsnum.h"#include "jsobj.h"#include "jsopcode.h"#include "jsparse.h"#include "jsscan.h"#include "jsscope.h"#include "jsscript.h"#include "jsstr.h"#if JS_HAS_XML_SUPPORT#include "jsxml.h"#endif#if JS_HAS_DESTRUCTURING#include "jsdhash.h"#endif/* * JS parsers, from lowest to highest precedence. * * Each parser takes a context, a token stream, and a tree context struct. * Each returns a parse node tree or null on error. */typedef JSParseNode *JSParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc);typedef JSParseNode *JSMemberParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,               JSBool allowCallSyntax);typedef JSParseNode *JSPrimaryParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,                JSTokenType tt, JSBool afterDot);static JSParser FunctionStmt;static JSParser FunctionExpr;static JSParser Statements;static JSParser Statement;static JSParser Variables;static JSParser Expr;static JSParser AssignExpr;static JSParser CondExpr;static JSParser OrExpr;static JSParser AndExpr;static JSParser BitOrExpr;static JSParser BitXorExpr;static JSParser BitAndExpr;static JSParser EqExpr;static JSParser RelExpr;static JSParser ShiftExpr;static JSParser AddExpr;static JSParser MulExpr;static JSParser UnaryExpr;static JSMemberParser MemberExpr;static JSPrimaryParser PrimaryExpr;/* * Insist that the next token be of type tt, or report errno and return null. * NB: this macro uses cx and ts from its lexical environment. */#define MUST_MATCH_TOKEN(tt, errno)                                           \    JS_BEGIN_MACRO                                                            \        if (js_GetToken(cx, ts) != tt) {                                      \            js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, \                            errno);                                           \            return NULL;                                                      \        }                                                                     \    JS_END_MACRO#define CHECK_RECURSION()                                                     \    JS_BEGIN_MACRO                                                            \        int stackDummy;                                                       \        if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {                           \            js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR, \                                        JSMSG_OVER_RECURSED);                 \            return NULL;                                                      \        }                                                                     \    JS_END_MACRO#ifdef METER_PARSENODESstatic uint32 parsenodes = 0;static uint32 maxparsenodes = 0;static uint32 recyclednodes = 0;#endifstatic JSParseNode *RecycleTree(JSParseNode *pn, JSTreeContext *tc){    JSParseNode *next;    if (!pn)        return NULL;    JS_ASSERT(pn != tc->nodeList);      /* catch back-to-back dup recycles */    next = pn->pn_next;    pn->pn_next = tc->nodeList;    tc->nodeList = pn;#ifdef METER_PARSENODES    recyclednodes++;#endif    return next;}static JSParseNode *NewOrRecycledNode(JSContext *cx, JSTreeContext *tc){    JSParseNode *pn;    pn = tc->nodeList;    if (!pn) {        JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool);        if (!pn)            JS_ReportOutOfMemory(cx);    } else {        tc->nodeList = pn->pn_next;        /* Recycle immediate descendents only, to save work and working set. */        switch (pn->pn_arity) {          case PN_FUNC:            RecycleTree(pn->pn_body, tc);            break;          case PN_LIST:            if (pn->pn_head) {                /* XXX check for dup recycles in the list */                *pn->pn_tail = tc->nodeList;                tc->nodeList = pn->pn_head;#ifdef METER_PARSENODES                recyclednodes += pn->pn_count;#endif            }            break;          case PN_TERNARY:            RecycleTree(pn->pn_kid1, tc);            RecycleTree(pn->pn_kid2, tc);            RecycleTree(pn->pn_kid3, tc);            break;          case PN_BINARY:            RecycleTree(pn->pn_left, tc);            RecycleTree(pn->pn_right, tc);            break;          case PN_UNARY:            RecycleTree(pn->pn_kid, tc);            break;          case PN_NAME:            RecycleTree(pn->pn_expr, tc);            break;          case PN_NULLARY:            break;        }    }#ifdef METER_PARSENODES    if (pn) {        parsenodes++;        if (parsenodes - recyclednodes > maxparsenodes)            maxparsenodes = parsenodes - recyclednodes;    }#endif    return pn;}/* * Allocate a JSParseNode from cx's temporary arena. */static JSParseNode *NewParseNode(JSContext *cx, JSTokenStream *ts, JSParseNodeArity arity,             JSTreeContext *tc){    JSParseNode *pn;    JSToken *tp;    pn = NewOrRecycledNode(cx, tc);    if (!pn)        return NULL;    tp = &CURRENT_TOKEN(ts);    pn->pn_type = tp->type;    pn->pn_pos = tp->pos;    pn->pn_op = JSOP_NOP;    pn->pn_arity = arity;    pn->pn_next = NULL;    pn->pn_ts = ts;    pn->pn_source = NULL;    return pn;}static JSParseNode *NewBinary(JSContext *cx, JSTokenType tt,          JSOp op, JSParseNode *left, JSParseNode *right,          JSTreeContext *tc){    JSParseNode *pn, *pn1, *pn2;    if (!left || !right)        return NULL;    /*     * Flatten a left-associative (left-heavy) tree of a given operator into     * a list, to reduce js_FoldConstants and js_EmitTree recursion.     */    if (left->pn_type == tt &&        left->pn_op == op &&        (js_CodeSpec[op].format & JOF_LEFTASSOC)) {        if (left->pn_arity != PN_LIST) {            pn1 = left->pn_left, pn2 = left->pn_right;            left->pn_arity = PN_LIST;            PN_INIT_LIST_1(left, pn1);            PN_APPEND(left, pn2);            if (tt == TOK_PLUS) {                if (pn1->pn_type == TOK_STRING)                    left->pn_extra |= PNX_STRCAT;                else if (pn1->pn_type != TOK_NUMBER)                    left->pn_extra |= PNX_CANTFOLD;                if (pn2->pn_type == TOK_STRING)                    left->pn_extra |= PNX_STRCAT;                else if (pn2->pn_type != TOK_NUMBER)                    left->pn_extra |= PNX_CANTFOLD;            }        }        PN_APPEND(left, right);        left->pn_pos.end = right->pn_pos.end;        if (tt == TOK_PLUS) {            if (right->pn_type == TOK_STRING)                left->pn_extra |= PNX_STRCAT;            else if (right->pn_type != TOK_NUMBER)                left->pn_extra |= PNX_CANTFOLD;        }        return left;    }    /*     * Fold constant addition immediately, to conserve node space and, what's     * more, so js_FoldConstants never sees mixed addition and concatenation     * operations with more than one leading non-string operand in a PN_LIST     * generated for expressions such as 1 + 2 + "pt" (which should evaluate     * to "3pt", not "12pt").     */    if (tt == TOK_PLUS &&        left->pn_type == TOK_NUMBER &&        right->pn_type == TOK_NUMBER) {        left->pn_dval += right->pn_dval;        left->pn_pos.end = right->pn_pos.end;        RecycleTree(right, tc);        return left;    }    pn = NewOrRecycledNode(cx, tc);    if (!pn)        return NULL;    pn->pn_type = tt;    pn->pn_pos.begin = left->pn_pos.begin;    pn->pn_pos.end = right->pn_pos.end;    pn->pn_op = op;    pn->pn_arity = PN_BINARY;    pn->pn_left = left;    pn->pn_right = right;    pn->pn_next = NULL;    pn->pn_ts = NULL;    pn->pn_source = NULL;    return pn;}#if JS_HAS_GETTER_SETTERstatic JSTokenTypeCheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt){    JSAtom *atom;    JSRuntime *rt;    JSOp op;    const char *name;    JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_NAME);    atom = CURRENT_TOKEN(ts).t_atom;    rt = cx->runtime;    if (atom == rt->atomState.getterAtom)        op = JSOP_GETTER;    else if (atom == rt->atomState.setterAtom)        op = JSOP_SETTER;    else        return TOK_NAME;    if (js_PeekTokenSameLine(cx, ts) != tt)        return TOK_NAME;    (void) js_GetToken(cx, ts);    if (CURRENT_TOKEN(ts).t_op != JSOP_NOP) {        js_ReportCompileErrorNumber(cx, ts, JSREPORT_TS | JSREPORT_ERROR,                                    JSMSG_BAD_GETTER_OR_SETTER,                                    (op == JSOP_GETTER)                                    ? js_getter_str                                    : js_setter_str);        return TOK_ERROR;    }    CURRENT_TOKEN(ts).t_op = op;    if (JS_HAS_STRICT_OPTION(cx)) {        name = js_AtomToPrintableString(cx, atom);        if (!name ||            !js_ReportCompileErrorNumber(cx, ts,                                         JSREPORT_TS |                                         JSREPORT_WARNING |                                         JSREPORT_STRICT,                                         JSMSG_DEPRECATED_USAGE,                                         name)) {            return TOK_ERROR;        }    }    return tt;}#endifstatic voidMaybeSetupFrame(JSContext *cx, JSObject *chain, JSStackFrame *oldfp,                JSStackFrame *newfp){    /*     * Always push a new frame if the current frame is special, so that     * Variables gets the correct variables object: the one from the special     * frame's caller.     */    if (oldfp &&        oldfp->varobj &&        oldfp->scopeChain == chain &&        !(oldfp->flags & JSFRAME_SPECIAL)) {

⌨️ 快捷键说明

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