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

📄 jsregexp.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
    return cu;}static jschardowncase(jschar ch){    jschar cl = JS_TOLOWER(ch);    if (cl >= 128 && ch < 128)        return ch;    return cl;}/* Construct and initialize an RENode, returning NULL for out-of-memory */static RENode *NewRENode(CompilerState *state, REOp op){    JSContext *cx;    RENode *ren;    cx = state->context;    JS_ARENA_ALLOCATE_CAST(ren, RENode *, &cx->tempPool, sizeof *ren);    if (!ren) {        JS_ReportOutOfMemory(cx);        return NULL;    }    ren->op = op;    ren->next = NULL;    ren->kid = NULL;    return ren;}/* * Validates and converts hex ascii value. */static JSBoolisASCIIHexDigit(jschar c, uintN *digit){    uintN cv = c;    if (cv < '0')        return JS_FALSE;    if (cv <= '9') {        *digit = cv - '0';        return JS_TRUE;    }    cv |= 0x20;    if (cv >= 'a' && cv <= 'f') {        *digit = cv - 'a' + 10;        return JS_TRUE;    }    return JS_FALSE;}typedef struct {    REOp op;    const jschar *errPos;    size_t parenIndex;} REOpData;/* * Process the op against the two top operands, reducing them to a single * operand in the penultimate slot. Update progLength and treeDepth. */static JSBoolProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack,          intN operandSP){    RENode *result;    switch (opData->op) {    case REOP_ALT:        result = NewRENode(state, REOP_ALT);        if (!result)            return JS_FALSE;        result->kid = operandStack[operandSP - 2];        result->u.kid2 = operandStack[operandSP - 1];        operandStack[operandSP - 2] = result;        if (state->treeDepth == TREE_DEPTH_MAX) {            js_ReportCompileErrorNumber(state->context, state->tokenStream,                                        JSREPORT_TS | JSREPORT_ERROR,                                        JSMSG_REGEXP_TOO_COMPLEX);            return JS_FALSE;        }        ++state->treeDepth;        /*         * Look at both alternates to see if there's a FLAT or a CLASS at         * the start of each. If so, use a prerequisite match.         */        if (((RENode *) result->kid)->op == REOP_FLAT &&            ((RENode *) result->u.kid2)->op == REOP_FLAT &&            (state->flags & JSREG_FOLD) == 0) {            result->op = REOP_ALTPREREQ;            result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;            result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr;            /* ALTPREREQ, <end>, uch1, uch2, <next>, ...,                                            JUMP, <end> ... ENDALT */            state->progLength += 13;        }        else        if (((RENode *) result->kid)->op == REOP_CLASS &&            ((RENode *) result->kid)->u.ucclass.index < 256 &&            ((RENode *) result->u.kid2)->op == REOP_FLAT &&            (state->flags & JSREG_FOLD) == 0) {            result->op = REOP_ALTPREREQ2;            result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr;            result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index;            /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,                                            JUMP, <end> ... ENDALT */            state->progLength += 13;        }        else        if (((RENode *) result->kid)->op == REOP_FLAT &&            ((RENode *) result->u.kid2)->op == REOP_CLASS &&            ((RENode *) result->u.kid2)->u.ucclass.index < 256 &&            (state->flags & JSREG_FOLD) == 0) {            result->op = REOP_ALTPREREQ2;            result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;            result->u.altprereq.ch2 =                ((RENode *) result->u.kid2)->u.ucclass.index;            /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,                                          JUMP, <end> ... ENDALT */            state->progLength += 13;        }        else {            /* ALT, <next>, ..., JUMP, <end> ... ENDALT */            state->progLength += 7;        }        break;    case REOP_CONCAT:        result = operandStack[operandSP - 2];        while (result->next)            result = result->next;        result->next = operandStack[operandSP - 1];        break;    case REOP_ASSERT:    case REOP_ASSERT_NOT:    case REOP_LPARENNON:    case REOP_LPAREN:        /* These should have been processed by a close paren. */        js_ReportCompileErrorNumberUC(state->context, state->tokenStream,                                      JSREPORT_TS | JSREPORT_ERROR,                                      JSMSG_MISSING_PAREN, opData->errPos);        return JS_FALSE;    default:;    }    return JS_TRUE;}/* * Parser forward declarations. */static JSBool ParseTerm(CompilerState *state);static JSBool ParseQuantifier(CompilerState *state);static intN ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues);/* * Top-down regular expression grammar, based closely on Perl4. * *  regexp:     altern                  A regular expression is one or more *              altern '|' regexp       alternatives separated by vertical bar. */#define INITIAL_STACK_SIZE  128static JSBoolParseRegExp(CompilerState *state){    size_t parenIndex;    RENode *operand;    REOpData *operatorStack;    RENode **operandStack;    REOp op;    intN i;    JSBool result = JS_FALSE;    intN operatorSP = 0, operatorStackSize = INITIAL_STACK_SIZE;    intN operandSP = 0, operandStackSize = INITIAL_STACK_SIZE;    /* Watch out for empty regexp */    if (state->cp == state->cpend) {        state->result = NewRENode(state, REOP_EMPTY);        return (state->result != NULL);    }    operatorStack = (REOpData *)        JS_malloc(state->context, sizeof(REOpData) * operatorStackSize);    if (!operatorStack)        return JS_FALSE;    operandStack = (RENode **)        JS_malloc(state->context, sizeof(RENode *) * operandStackSize);    if (!operandStack)        goto out;    for (;;) {        parenIndex = state->parenCount;        if (state->cp == state->cpend) {            /*             * If we are at the end of the regexp and we're short one or more             * operands, the regexp must have the form /x|/ or some such, with             * left parentheses making us short more than one operand.             */            if (operatorSP >= operandSP) {                operand = NewRENode(state, REOP_EMPTY);                if (!operand)                    goto out;                goto pushOperand;            }        } else {            switch (*state->cp) {            case '(':                ++state->cp;                if (state->cp + 1 < state->cpend &&                    *state->cp == '?' &&                    (state->cp[1] == '=' ||                     state->cp[1] == '!' ||                     state->cp[1] == ':')) {                    switch (state->cp[1]) {                    case '=':                        op = REOP_ASSERT;                        /* ASSERT, <next>, ... ASSERTTEST */                        state->progLength += 4;                        break;                    case '!':                        op = REOP_ASSERT_NOT;                        /* ASSERTNOT, <next>, ... ASSERTNOTTEST */                        state->progLength += 4;                        break;                    default:                        op = REOP_LPARENNON;                        break;                    }                    state->cp += 2;                } else {                    op = REOP_LPAREN;                    /* LPAREN, <index>, ... RPAREN, <index> */                    state->progLength                        += 2 * (1 + GetCompactIndexWidth(parenIndex));                    state->parenCount++;                    if (state->parenCount == 65535) {                        js_ReportCompileErrorNumber(state->context,                                                    state->tokenStream,                                                    JSREPORT_TS |                                                    JSREPORT_ERROR,                                                    JSMSG_TOO_MANY_PARENS);                        goto out;                    }                }                goto pushOperator;            case ')':                /*                 * If there's no stacked open parenthesis, throw syntax error.                 */                for (i = operatorSP - 1; ; i--) {                    if (i < 0) {                        js_ReportCompileErrorNumber(state->context,                                                    state->tokenStream,                                                    JSREPORT_TS |                                                    JSREPORT_ERROR,                                                    JSMSG_UNMATCHED_RIGHT_PAREN);                        goto out;                    }                    if (operatorStack[i].op == REOP_ASSERT ||                        operatorStack[i].op == REOP_ASSERT_NOT ||                        operatorStack[i].op == REOP_LPARENNON ||                        operatorStack[i].op == REOP_LPAREN) {                        break;                    }                }                /* FALL THROUGH */            case '|':                /* Expected an operand before these, so make an empty one */                operand = NewRENode(state, REOP_EMPTY);                if (!operand)                    goto out;                goto pushOperand;            default:                if (!ParseTerm(state))                    goto out;                operand = state->result;pushOperand:                if (operandSP == operandStackSize) {                    operandStackSize += operandStackSize;                    operandStack = (RENode **)                        JS_realloc(state->context, operandStack,                                   sizeof(RENode *) * operandStackSize);                    if (!operandStack)                        goto out;                }                operandStack[operandSP++] = operand;                break;            }        }        /* At the end; process remaining operators. */restartOperator:        if (state->cp == state->cpend) {            while (operatorSP) {                --operatorSP;                if (!ProcessOp(state, &operatorStack[operatorSP],                               operandStack, operandSP))                    goto out;                --operandSP;            }            JS_ASSERT(operandSP == 1);            state->result = operandStack[0];            result = JS_TRUE;            goto out;        }        switch (*state->cp) {        case '|':            /* Process any stacked 'concat' operators */            ++state->cp;            while (operatorSP &&                   operatorStack[operatorSP - 1].op == REOP_CONCAT) {                --operatorSP;                if (!ProcessOp(state, &operatorStack[operatorSP],                               operandStack, operandSP)) {                    goto out;                }                --operandSP;            }            op = REOP_ALT;            goto pushOperator;        case ')':            /*             * If there's no stacked open parenthesis, throw syntax error.             */            for (i = operatorSP - 1; ; i--) {                if (i < 0) {                    js_ReportCompileErrorNumber(state->context,                                                state->tokenStream,                                                JSREPORT_TS | JSREPORT_ERROR,                                                JSMSG_UNMATCHED_RIGHT_PAREN);                    goto out;                }                if (operatorStack[i].op == REOP_ASSERT ||                    operatorStack[i].op == REOP_ASSERT_NOT ||                    operatorStack[i].op == REOP_LPARENNON ||                    operatorStack[i].op == REOP_LPAREN) {                    break;                }            }            ++state->cp;            /* Process everything on the stack until the open parenthesis. */            for (;;) {                JS_ASSERT(operatorSP);

⌨️ 快捷键说明

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