Search in sources :

Example 1 with RegExMatch

use of org.mvel2.ast.RegExMatch in project mvel by mikebrock.

the class AbstractParser method nextToken.

/**
 * Retrieve the next token in the expression.
 *
 * @return -
 */
protected ASTNode nextToken() {
    try {
        /**
         * If the cursor is at the end of the expression, we have nothing more to do:
         * return null.
         */
        if (!splitAccumulator.isEmpty()) {
            lastNode = (ASTNode) splitAccumulator.pop();
            if (cursor >= end && lastNode instanceof EndOfStatement) {
                return nextToken();
            } else {
                return lastNode;
            }
        } else if (cursor >= end) {
            return null;
        }
        int brace, idx;
        int tmpStart;
        String name;
        /**
         * Because of parser recursion for sub-expression parsing, we sometimes need to remain
         * certain field states.  We do not reset for assignments, boolean mode, list creation or
         * a capture only mode.
         */
        boolean capture = false, union = false;
        if ((fields & ASTNode.COMPILE_IMMEDIATE) != 0 && pCtx == null) {
            debugSymbols = (pCtx = getParserContext()).isDebugSymbols();
        }
        if (debugSymbols) {
            if (!lastWasLineLabel) {
                if (pCtx.getSourceFile() == null) {
                    throw new CompileException("unable to produce debugging symbols: source name must be provided.", expr, st);
                }
                if (!pCtx.isLineMapped(pCtx.getSourceFile())) {
                    pCtx.initLineMapping(pCtx.getSourceFile(), expr);
                }
                skipWhitespace();
                if (cursor >= end) {
                    return null;
                }
                int line = pCtx.getLineFor(pCtx.getSourceFile(), cursor);
                if (!pCtx.isVisitedLine(pCtx.getSourceFile(), pCtx.setLineCount(line)) && !pCtx.isBlockSymbols()) {
                    lastWasLineLabel = true;
                    pCtx.visitLine(pCtx.getSourceFile(), line);
                    return lastNode = pCtx.setLastLineLabel(new LineLabel(pCtx.getSourceFile(), line));
                }
            } else {
                lastWasComment = lastWasLineLabel = false;
            }
        }
        /**
         * Skip any whitespace currently under the starting point.
         */
        skipWhitespace();
        /**
         * From here to the end of the method is the core MVEL parsing code.  Fiddling around here is asking for
         * trouble unless you really know what you're doing.
         */
        st = cursor;
        Mainloop: while (cursor != end) {
            if (isIdentifierPart(expr[cursor])) {
                capture = true;
                cursor++;
                while (cursor != end && isIdentifierPart(expr[cursor])) cursor++;
            }
            if (capture) {
                String t;
                if (OPERATORS.containsKey(t = new String(expr, st, cursor - st))) {
                    switch(OPERATORS.get(t)) {
                        case NEW:
                            if (!isIdentifierPart(expr[st = cursor = trimRight(cursor)])) {
                                throw new CompileException("unexpected character (expected identifier): " + expr[cursor], expr, st);
                            }
                            /**
                             * Capture the beginning part of the token.
                             */
                            do {
                                captureToNextTokenJunction();
                                skipWhitespace();
                            } while (cursor < end && expr[cursor] == '[');
                            /**
                             * If it's not a dimentioned array, continue capturing if necessary.
                             */
                            if (cursor < end && !lastNonWhite(']'))
                                captureToEOT();
                            TypeDescriptor descr = new TypeDescriptor(expr, st, trimLeft(cursor) - st, fields);
                            if (pCtx == null)
                                pCtx = getParserContext();
                            if (pCtx.hasProtoImport(descr.getClassName())) {
                                return lastNode = new NewPrototypeNode(descr);
                            }
                            lastNode = new NewObjectNode(descr, fields, pCtx);
                            skipWhitespace();
                            if (cursor != end && expr[cursor] == '{') {
                                if (!((NewObjectNode) lastNode).getTypeDescr().isUndimensionedArray()) {
                                    throw new CompileException("conflicting syntax: dimensioned array with initializer block", expr, st);
                                }
                                st = cursor;
                                Class egressType = lastNode.getEgressType();
                                if (egressType == null) {
                                    try {
                                        egressType = getClassReference(pCtx, descr);
                                    } catch (ClassNotFoundException e) {
                                        throw new CompileException("could not instantiate class", expr, st, e);
                                    }
                                }
                                cursor = balancedCaptureWithLineAccounting(expr, st, end, expr[cursor], pCtx) + 1;
                                if (tokenContinues()) {
                                    lastNode = new InlineCollectionNode(expr, st, cursor - st, fields, egressType, pCtx);
                                    st = cursor;
                                    captureToEOT();
                                    return lastNode = new Union(expr, st + 1, cursor, fields, lastNode);
                                } else {
                                    return lastNode = new InlineCollectionNode(expr, st, cursor - st, fields, egressType, pCtx);
                                }
                            } else if (((NewObjectNode) lastNode).getTypeDescr().isUndimensionedArray()) {
                                throw new CompileException("array initializer expected", expr, st);
                            }
                            st = cursor;
                            return lastNode;
                        case ASSERT:
                            st = cursor = trimRight(cursor);
                            captureToEOS();
                            return lastNode = new AssertNode(expr, st, cursor-- - st, fields, pCtx);
                        case RETURN:
                            st = cursor = trimRight(cursor);
                            captureToEOS();
                            return lastNode = new ReturnNode(expr, st, cursor - st, fields, pCtx);
                        case IF:
                            return captureCodeBlock(ASTNode.BLOCK_IF);
                        case ELSE:
                            throw new CompileException("else without if", expr, st);
                        case FOREACH:
                            return captureCodeBlock(ASTNode.BLOCK_FOREACH);
                        case WHILE:
                            return captureCodeBlock(ASTNode.BLOCK_WHILE);
                        case UNTIL:
                            return captureCodeBlock(ASTNode.BLOCK_UNTIL);
                        case FOR:
                            return captureCodeBlock(ASTNode.BLOCK_FOR);
                        case WITH:
                            return captureCodeBlock(ASTNode.BLOCK_WITH);
                        case DO:
                            return captureCodeBlock(ASTNode.BLOCK_DO);
                        case PROTO:
                            return captureCodeBlock(PROTO);
                        case ISDEF:
                            st = cursor = trimRight(cursor);
                            captureToNextTokenJunction();
                            return lastNode = new IsDef(expr, st, cursor - st);
                        case IMPORT:
                            st = cursor = trimRight(cursor);
                            captureToEOS();
                            ImportNode importNode = new ImportNode(expr, st, cursor - st);
                            if (pCtx == null)
                                pCtx = getParserContext();
                            if (importNode.isPackageImport()) {
                                pCtx.addPackageImport(importNode.getPackageImport());
                            } else {
                                pCtx.addImport(importNode.getImportClass().getSimpleName(), importNode.getImportClass());
                            }
                            return lastNode = importNode;
                        case IMPORT_STATIC:
                            st = cursor = trimRight(cursor);
                            captureToEOS();
                            return lastNode = new StaticImportNode(expr, st, trimLeft(cursor) - st);
                        case FUNCTION:
                            lastNode = captureCodeBlock(FUNCTION);
                            st = cursor + 1;
                            return lastNode;
                        case UNTYPED_VAR:
                            int end;
                            st = cursor + 1;
                            while (true) {
                                captureToEOT();
                                end = cursor;
                                skipWhitespace();
                                if (cursor != end && expr[cursor] == '=') {
                                    if (end == (cursor = st))
                                        throw new CompileException("illegal use of reserved word: var", expr, st);
                                    continue Mainloop;
                                } else {
                                    name = new String(expr, st, end - st);
                                    if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        splitAccumulator.add(lastNode = new IndexedDeclTypedVarNode(idx, st, end - st, Object.class));
                                    } else {
                                        splitAccumulator.add(lastNode = new DeclTypedVarNode(name, expr, st, end - st, Object.class, fields, pCtx));
                                    }
                                }
                                if (cursor == this.end || expr[cursor] != ',')
                                    break;
                                else {
                                    cursor++;
                                    skipWhitespace();
                                    st = cursor;
                                }
                            }
                            return (ASTNode) splitAccumulator.pop();
                    }
                }
                skipWhitespace();
                /**
                 * If we *were* capturing a token, and we just hit a non-identifier
                 * character, we stop and figure out what to do.
                 */
                if (cursor != end && expr[cursor] == '(') {
                    cursor = balancedCaptureWithLineAccounting(expr, cursor, end, '(', pCtx) + 1;
                }
                /**
                 * If we encounter any of the following cases, we are still dealing with
                 * a contiguous token.
                 */
                CaptureLoop: while (cursor != end) {
                    switch(expr[cursor]) {
                        case '.':
                            union = true;
                            cursor++;
                            skipWhitespace();
                            continue;
                        case '?':
                            if (lookToLast() == '.') {
                                union = true;
                                cursor++;
                                continue;
                            } else {
                                break CaptureLoop;
                            }
                        case '+':
                            switch(lookAhead()) {
                                case '+':
                                    name = new String(subArray(st, trimLeft(cursor)));
                                    if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        lastNode = new IndexedPostFixIncNode(idx, pCtx);
                                    } else {
                                        lastNode = new PostFixIncNode(name, pCtx);
                                    }
                                    cursor += 2;
                                    expectEOS();
                                    return lastNode;
                                case '=':
                                    name = createStringTrimmed(expr, st, cursor - st);
                                    st = cursor += 2;
                                    captureToEOS();
                                    if (union) {
                                        return lastNode = new DeepAssignmentNode(expr, st = trimRight(st), trimLeft(cursor) - st, fields, ADD, name, pCtx);
                                    } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        return lastNode = new IndexedAssignmentNode(expr, st, cursor - st, fields, ADD, name, idx, pCtx);
                                    } else {
                                        return lastNode = new OperativeAssign(name, expr, st = trimRight(st), trimLeft(cursor) - st, ADD, fields, pCtx);
                                    }
                            }
                            if (isDigit(lookAhead()) && cursor > 1 && (expr[cursor - 1] == 'E' || expr[cursor - 1] == 'e') && isDigit(expr[cursor - 2])) {
                                cursor++;
                                // capture = true;
                                continue Mainloop;
                            }
                            break CaptureLoop;
                        case '-':
                            switch(lookAhead()) {
                                case '-':
                                    name = new String(subArray(st, trimLeft(cursor)));
                                    if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        lastNode = new IndexedPostFixDecNode(idx, pCtx);
                                    } else {
                                        lastNode = new PostFixDecNode(name, pCtx);
                                    }
                                    cursor += 2;
                                    expectEOS();
                                    return lastNode;
                                case '=':
                                    name = new String(expr, st, trimLeft(cursor) - st);
                                    st = cursor += 2;
                                    captureToEOS();
                                    if (union) {
                                        return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields, SUB, t, pCtx);
                                    } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, SUB, idx, fields, pCtx);
                                    } else {
                                        return lastNode = new OperativeAssign(name, expr, st, cursor - st, SUB, fields, pCtx);
                                    }
                            }
                            if (isDigit(lookAhead()) && cursor > 1 && (expr[cursor - 1] == 'E' || expr[cursor - 1] == 'e') && isDigit(expr[cursor - 2])) {
                                cursor++;
                                capture = true;
                                continue Mainloop;
                            }
                            break CaptureLoop;
                        /**
                         * Exit immediately for any of these cases.
                         */
                        case '!':
                        case ',':
                        case '"':
                        case '\'':
                        case ';':
                        case ':':
                            break CaptureLoop;
                        // special compact code for recursive parses
                        case '\u00AB':
                        case '\u00BB':
                        case '\u00AC':
                        case '&':
                        case '^':
                        case '|':
                        case '*':
                        case '/':
                        case '%':
                            char op = expr[cursor];
                            if (lookAhead() == '=') {
                                name = new String(expr, st, trimLeft(cursor) - st);
                                st = cursor += 2;
                                captureToEOS();
                                if (union) {
                                    return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields, opLookup(op), t, pCtx);
                                } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                    return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, opLookup(op), idx, fields, pCtx);
                                } else {
                                    return lastNode = new OperativeAssign(name, expr, st, cursor - st, opLookup(op), fields, pCtx);
                                }
                            }
                            break CaptureLoop;
                        case '<':
                            if ((lookAhead() == '<' && lookAhead(2) == '=')) {
                                name = new String(expr, st, trimLeft(cursor) - st);
                                st = cursor += 3;
                                captureToEOS();
                                if (union) {
                                    return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields, BW_SHIFT_LEFT, t, pCtx);
                                } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                    return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, BW_SHIFT_LEFT, idx, fields, pCtx);
                                } else {
                                    return lastNode = new OperativeAssign(name, expr, st, cursor - st, BW_SHIFT_LEFT, fields, pCtx);
                                }
                            }
                            break CaptureLoop;
                        case '>':
                            if (lookAhead() == '>') {
                                if (lookAhead(2) == '=') {
                                    name = new String(expr, st, trimLeft(cursor) - st);
                                    st = cursor += 3;
                                    captureToEOS();
                                    if (union) {
                                        return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields, BW_SHIFT_RIGHT, t, pCtx);
                                    } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, BW_SHIFT_RIGHT, idx, fields, pCtx);
                                    } else {
                                        return lastNode = new OperativeAssign(name, expr, st, cursor - st, BW_SHIFT_RIGHT, fields, pCtx);
                                    }
                                } else if ((lookAhead(2) == '>' && lookAhead(3) == '=')) {
                                    name = new String(expr, st, trimLeft(cursor) - st);
                                    st = cursor += 4;
                                    captureToEOS();
                                    if (union) {
                                        return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields, BW_USHIFT_RIGHT, t, pCtx);
                                    } else if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                        return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, BW_USHIFT_RIGHT, idx, fields, pCtx);
                                    } else {
                                        return lastNode = new OperativeAssign(name, expr, st, cursor - st, BW_USHIFT_RIGHT, fields, pCtx);
                                    }
                                }
                            }
                            break CaptureLoop;
                        case '(':
                            cursor = balancedCaptureWithLineAccounting(expr, cursor, end, '(', pCtx) + 1;
                            continue;
                        case '[':
                            cursor = balancedCaptureWithLineAccounting(expr, cursor, end, '[', pCtx) + 1;
                            continue;
                        case '{':
                            if (!union)
                                break CaptureLoop;
                            cursor = balancedCaptureWithLineAccounting(expr, cursor, end, '{', pCtx) + 1;
                            continue;
                        case '~':
                            if (lookAhead() == '=') {
                                // tmp = subArray(start, trimLeft(cursor));
                                tmpStart = st;
                                int tmpOffset = cursor - st;
                                st = cursor += 2;
                                captureToEOT();
                                return lastNode = new RegExMatch(expr, tmpStart, tmpOffset, fields, st, cursor - st, pCtx);
                            }
                            break CaptureLoop;
                        case '=':
                            if (lookAhead() == '+') {
                                name = new String(expr, st, trimLeft(cursor) - st);
                                st = cursor += 2;
                                if (!isNextIdentifierOrLiteral()) {
                                    throw new CompileException("unexpected symbol '" + expr[cursor] + "'", expr, st);
                                }
                                captureToEOS();
                                if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                    return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, ADD, idx, fields, pCtx);
                                } else {
                                    return lastNode = new OperativeAssign(name, expr, st, cursor - st, ADD, fields, pCtx);
                                }
                            } else if (lookAhead() == '-') {
                                name = new String(expr, st, trimLeft(cursor) - st);
                                st = cursor += 2;
                                if (!isNextIdentifierOrLiteral()) {
                                    throw new CompileException("unexpected symbol '" + expr[cursor] + "'", expr, st);
                                }
                                captureToEOS();
                                if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                    return lastNode = new IndexedOperativeAssign(expr, st, cursor - st, SUB, idx, fields, pCtx);
                                } else {
                                    return lastNode = new OperativeAssign(name, expr, st, cursor - st, SUB, fields, pCtx);
                                }
                            }
                            if (greedy && lookAhead() != '=') {
                                cursor++;
                                if (union) {
                                    captureToEOS();
                                    return lastNode = new DeepAssignmentNode(expr, st, cursor - st, fields | ASTNode.ASSIGN, pCtx);
                                } else if (lastWasIdentifier) {
                                    return procTypedNode(false);
                                } else if (pCtx != null && ((idx = pCtx.variableIndexOf(t)) != -1 && (pCtx.isIndexAllocation()))) {
                                    captureToEOS();
                                    IndexedAssignmentNode ian = new IndexedAssignmentNode(expr, st = trimRight(st), trimLeft(cursor) - st, ASTNode.ASSIGN, idx, pCtx);
                                    if (idx == -1) {
                                        pCtx.addIndexedInput(t = ian.getAssignmentVar());
                                        ian.setRegister(pCtx.variableIndexOf(t));
                                    }
                                    return lastNode = ian;
                                } else {
                                    captureToEOS();
                                    return lastNode = new AssignmentNode(expr, st, cursor - st, fields | ASTNode.ASSIGN, pCtx);
                                }
                            }
                            break CaptureLoop;
                        default:
                            if (cursor != end) {
                                if (isIdentifierPart(expr[cursor])) {
                                    if (!union) {
                                        break CaptureLoop;
                                    }
                                    cursor++;
                                    while (cursor != end && isIdentifierPart(expr[cursor])) cursor++;
                                } else if ((cursor + 1) != end && isIdentifierPart(expr[cursor + 1])) {
                                    break CaptureLoop;
                                } else {
                                    cursor++;
                                }
                            } else {
                                break CaptureLoop;
                            }
                    }
                }
                /**
                 * Produce the token.
                 */
                trimWhitespace();
                return createPropertyToken(st, cursor);
            } else {
                switch(expr[cursor]) {
                    case '.':
                        {
                            cursor++;
                            if (isDigit(expr[cursor])) {
                                capture = true;
                                continue;
                            }
                            expectNextChar_IW('{');
                            return lastNode = new ThisWithNode(expr, st, cursor - st - 1, cursor + 1, (cursor = balancedCaptureWithLineAccounting(expr, cursor, end, '{', pCtx) + 1) - 3, fields, pCtx);
                        }
                    case '@':
                        {
                            st++;
                            captureToEOT();
                            if (pCtx == null || (pCtx.getInterceptors() == null || !pCtx.getInterceptors().containsKey(name = new String(expr, st, cursor - st)))) {
                                throw new CompileException("reference to undefined interceptor: " + new String(expr, st, cursor - st), expr, st);
                            }
                            return lastNode = new InterceptorWrapper(pCtx.getInterceptors().get(name), nextToken());
                        }
                    case '=':
                        return createOperator(expr, st, (cursor += 2));
                    case '-':
                        if (lookAhead() == '-') {
                            cursor += 2;
                            skipWhitespace();
                            st = cursor;
                            captureIdentifier();
                            name = new String(subArray(st, cursor));
                            if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                return lastNode = new IndexedPreFixDecNode(idx, pCtx);
                            } else {
                                return lastNode = new PreFixDecNode(name, pCtx);
                            }
                        } else if ((cursor == start || (lastNode != null && (lastNode instanceof BooleanNode || lastNode.isOperator()))) && !isDigit(lookAhead())) {
                            captureToEOT();
                            return new Sign(expr, st, cursor - st, fields, pCtx);
                        } else if ((cursor != start && !isWhitespace(expr[cursor - 1]) && (!(lastNode != null && (lastNode instanceof BooleanNode || lastNode.isOperator())))) || !isDigit(lookAhead())) {
                            return createOperator(expr, st, cursor++ + 1);
                        } else if ((cursor - 1) != start || (!isDigit(expr[cursor - 1])) && isDigit(lookAhead())) {
                            cursor++;
                            break;
                        } else {
                            throw new CompileException("not a statement", expr, st);
                        }
                    case '+':
                        if (lookAhead() == '+') {
                            cursor += 2;
                            skipWhitespace();
                            st = cursor;
                            captureIdentifier();
                            name = new String(subArray(st, cursor));
                            if (pCtx != null && (idx = pCtx.variableIndexOf(name)) != -1) {
                                return lastNode = new IndexedPreFixIncNode(idx, pCtx);
                            } else {
                                return lastNode = new PreFixIncNode(name, pCtx);
                            }
                        }
                        return createOperator(expr, st, cursor++ + 1);
                    case '*':
                        if (lookAhead() == '*') {
                            cursor++;
                        }
                        return createOperator(expr, st, cursor++ + 1);
                    case ';':
                        cursor++;
                        lastWasIdentifier = false;
                        return lastNode = new EndOfStatement();
                    case '#':
                    case '/':
                    case '?':
                    case ':':
                    case '^':
                    case '%':
                        {
                            return createOperator(expr, st, cursor++ + 1);
                        }
                    case '(':
                        {
                            cursor++;
                            boolean singleToken = true;
                            skipWhitespace();
                            for (brace = 1; cursor != end && brace != 0; cursor++) {
                                switch(expr[cursor]) {
                                    case '(':
                                        brace++;
                                        break;
                                    case ')':
                                        brace--;
                                        break;
                                    case '\'':
                                        cursor = captureStringLiteral('\'', expr, cursor, end);
                                        break;
                                    case '"':
                                        cursor = captureStringLiteral('"', expr, cursor, end);
                                        break;
                                    case 'i':
                                        if (brace == 1 && isWhitespace(lookBehind()) && lookAhead() == 'n' && isWhitespace(lookAhead(2))) {
                                            for (int level = brace; cursor != end; cursor++) {
                                                switch(expr[cursor]) {
                                                    case '(':
                                                        brace++;
                                                        break;
                                                    case ')':
                                                        if (--brace < level) {
                                                            cursor++;
                                                            if (tokenContinues()) {
                                                                lastNode = new Fold(expr, trimRight(st + 1), cursor - st - 2, fields, pCtx);
                                                                if (expr[st = cursor] == '.')
                                                                    st++;
                                                                captureToEOT();
                                                                return lastNode = new Union(expr, st = trimRight(st), cursor - st, fields, lastNode);
                                                            } else {
                                                                return lastNode = new Fold(expr, trimRight(st + 1), cursor - st - 2, fields, pCtx);
                                                            }
                                                        }
                                                        break;
                                                    case '\'':
                                                        cursor = captureStringLiteral('\'', expr, cursor, end);
                                                        break;
                                                    case '"':
                                                        cursor = captureStringLiteral('\"', expr, cursor, end);
                                                        break;
                                                }
                                            }
                                            throw new CompileException("unterminated projection; closing parathesis required", expr, st);
                                        }
                                        break;
                                    default:
                                        if (expr[cursor] != '.') {
                                            switch(expr[cursor]) {
                                                case '[':
                                                case ']':
                                                    break;
                                                default:
                                                    if (!(isIdentifierPart(expr[cursor]) || expr[cursor] == '.')) {
                                                        singleToken = false;
                                                    }
                                            }
                                        }
                                }
                            }
                            if (brace != 0) {
                                throw new CompileException("unbalanced braces in expression: (" + brace + "):", expr, st);
                            }
                            tmpStart = -1;
                            if (singleToken) {
                                int _st;
                                TypeDescriptor tDescr = new TypeDescriptor(expr, _st = trimRight(st + 1), trimLeft(cursor - 1) - _st, fields);
                                Class cls;
                                try {
                                    if (tDescr.isClass() && (cls = getClassReference(pCtx, tDescr)) != null) {
                                        st = cursor;
                                        captureToEOS();
                                        return lastNode = new TypeCast(expr, st, cursor - st, cls, fields, pCtx);
                                    }
                                } catch (ClassNotFoundException e) {
                                // fallthrough
                                }
                            }
                            if (tmpStart != -1) {
                                return handleUnion(handleSubstatement(new Substatement(expr, tmpStart, cursor - tmpStart, fields, pCtx)));
                            } else {
                                return handleUnion(handleSubstatement(new Substatement(expr, st = trimRight(st + 1), trimLeft(cursor - 1) - st, fields, pCtx)));
                            }
                        }
                    case '}':
                    case ']':
                    case ')':
                        {
                            throw new CompileException("unbalanced braces", expr, st);
                        }
                    case '>':
                        {
                            switch(expr[cursor + 1]) {
                                case '>':
                                    if (expr[cursor += 2] == '>')
                                        cursor++;
                                    return createOperator(expr, st, cursor);
                                case '=':
                                    return createOperator(expr, st, cursor += 2);
                                default:
                                    return createOperator(expr, st, ++cursor);
                            }
                        }
                    case '<':
                        {
                            if (expr[++cursor] == '<') {
                                if (expr[++cursor] == '<')
                                    cursor++;
                                return createOperator(expr, st, cursor);
                            } else if (expr[cursor] == '=') {
                                return createOperator(expr, st, ++cursor);
                            } else {
                                return createOperator(expr, st, cursor);
                            }
                        }
                    case '\'':
                    case '"':
                        lastNode = new LiteralNode(handleStringEscapes(subset(expr, st + 1, (cursor = captureStringLiteral(expr[cursor], expr, cursor, end)) - st - 1)), String.class);
                        cursor++;
                        if (tokenContinues()) {
                            return lastNode = handleUnion(lastNode);
                        }
                        return lastNode;
                    case '&':
                        {
                            if (expr[cursor++ + 1] == '&') {
                                return createOperator(expr, st, ++cursor);
                            } else {
                                return createOperator(expr, st, cursor);
                            }
                        }
                    case '|':
                        {
                            if (expr[cursor++ + 1] == '|') {
                                return createOperator(expr, st, ++cursor);
                            } else {
                                return createOperator(expr, st, cursor);
                            }
                        }
                    case '~':
                        if ((cursor++ - 1 != 0 || !isIdentifierPart(lookBehind())) && isDigit(expr[cursor])) {
                            st = cursor;
                            captureToEOT();
                            return lastNode = new Invert(expr, st, cursor - st, fields, pCtx);
                        } else if (expr[cursor] == '(') {
                            st = cursor--;
                            captureToEOT();
                            return lastNode = new Invert(expr, st, cursor - st, fields, pCtx);
                        } else {
                            if (expr[cursor] == '=')
                                cursor++;
                            return createOperator(expr, st, cursor);
                        }
                    case '!':
                        {
                            ++cursor;
                            if (isNextIdentifier()) {
                                if (lastNode != null && !lastNode.isOperator()) {
                                    throw new CompileException("unexpected operator '!'", expr, st);
                                }
                                st = cursor;
                                captureToEOT();
                                if ("new".equals(name = new String(expr, st, cursor - st)) || "isdef".equals(name)) {
                                    captureToEOT();
                                    return lastNode = new Negation(expr, st, cursor - st, fields, pCtx);
                                } else {
                                    return lastNode = new Negation(expr, st, cursor - st, fields, pCtx);
                                }
                            } else if (expr[cursor] == '(') {
                                st = cursor--;
                                captureToEOT();
                                return lastNode = new Negation(expr, st, cursor - st, fields, pCtx);
                            } else if (expr[cursor] != '=')
                                throw new CompileException("unexpected operator '!'", expr, st, null);
                            else {
                                return createOperator(expr, st, ++cursor);
                            }
                        }
                    case '[':
                    case '{':
                        cursor = balancedCaptureWithLineAccounting(expr, cursor, end, expr[cursor], pCtx) + 1;
                        if (tokenContinues()) {
                            lastNode = new InlineCollectionNode(expr, st, cursor - st, fields, pCtx);
                            st = cursor;
                            captureToEOT();
                            if (expr[st] == '.')
                                st++;
                            return lastNode = new Union(expr, st, cursor - st, fields, lastNode);
                        } else {
                            return lastNode = new InlineCollectionNode(expr, st, cursor - st, fields, pCtx);
                        }
                    default:
                        cursor++;
                }
            }
        }
        if (st == cursor)
            return null;
        else
            return createPropertyToken(st, cursor);
    } catch (RedundantCodeException e) {
        return nextToken();
    } catch (NumberFormatException e) {
        throw new CompileException("badly formatted number: " + e.getMessage(), expr, st, e);
    } catch (StringIndexOutOfBoundsException e) {
        throw new CompileException("unexpected end of statement", expr, cursor, e);
    } catch (ArrayIndexOutOfBoundsException e) {
        throw new CompileException("unexpected end of statement", expr, cursor, e);
    } catch (CompileException e) {
        throw ErrorUtil.rewriteIfNeeded(e, expr, cursor);
    }
}
Also used : CompileException(org.mvel2.CompileException)

Example 2 with RegExMatch

use of org.mvel2.ast.RegExMatch in project drools by kiegroup.

the class ConditionAnalyzer method analyzeSingleCondition.

private SingleCondition analyzeSingleCondition(ASTNode node, boolean isNegated) {
    SingleCondition condition = new SingleCondition(isNegated);
    if (node instanceof BinaryOperation) {
        BinaryOperation binaryOperation = (BinaryOperation) node;
        condition.left = analyzeNode(binaryOperation.getLeft());
        condition.operation = BooleanOperator.fromMvelOpCode(binaryOperation.getOperation());
        condition.right = analyzeNode(binaryOperation.getRight());
    } else if (node instanceof RegExMatch) {
        condition.left = analyzeNode(node);
        condition.operation = BooleanOperator.MATCHES;
        RegExMatch regExNode = (RegExMatch) node;
        Pattern pattern = regExNode.getPattern();
        if (pattern != null) {
            condition.right = new FixedExpression(String.class, pattern.pattern());
        } else {
            condition.right = analyzeNode(((ExecutableAccessor) regExNode.getPatternStatement()).getNode());
        }
    } else if (node instanceof Contains) {
        condition.left = analyzeNode(((Contains) node).getFirstStatement());
        condition.operation = BooleanOperator.CONTAINS;
        condition.right = analyzeNode(((Contains) node).getSecondStatement());
    } else if (node instanceof Soundslike) {
        condition.left = analyzeNode(((Soundslike) node).getStatement());
        condition.operation = BooleanOperator.SOUNDSLIKE;
        condition.right = analyzeNode(((Soundslike) node).getSoundslike());
    } else if (node instanceof Instance) {
        condition.left = analyzeNode(((Instance) node).getStatement());
        condition.operation = BooleanOperator.INSTANCEOF;
        condition.right = analyzeNode(((Instance) node).getClassStatement());
    } else {
        condition.left = analyzeNode(node);
    }
    return condition;
}
Also used : Pattern(java.util.regex.Pattern) RegExMatch(org.mvel2.ast.RegExMatch) Soundslike(org.mvel2.ast.Soundslike) Instance(org.mvel2.ast.Instance) BinaryOperation(org.mvel2.ast.BinaryOperation) Contains(org.mvel2.ast.Contains)

Aggregations

Pattern (java.util.regex.Pattern)1 CompileException (org.mvel2.CompileException)1 BinaryOperation (org.mvel2.ast.BinaryOperation)1 Contains (org.mvel2.ast.Contains)1 Instance (org.mvel2.ast.Instance)1 RegExMatch (org.mvel2.ast.RegExMatch)1 Soundslike (org.mvel2.ast.Soundslike)1