Search in sources :

Example 31 with And

use of org.mvel2.ast.And 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 32 with And

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

the class CoreConfidenceTests method testStringConcatenation.

public void testStringConcatenation() {
    // debugging MVEL code, it seems that MVEL 'thinks' that the result of the expression:
    // "Drop +5%: "+$sb+" avg: $"+$av+" price: $"+$pr
    // is a double, and as so, he looks for a method:
    // Services.log( double );
    // but finds only:
    // Services.log( String );
    // raising the error.
    String ex = "services.log((String) \"Drop +5%: \"+$sb+\" avg: $\"+$av+\" price: $\"+$pr );";
    ParserContext ctx = new ParserContext();
    ctx.setStrongTyping(true);
    ctx.addInput("$sb", String.class);
    ctx.addInput("$av", double.class);
    ctx.addInput("$pr", double.class);
    ctx.addInput("services", Services.class);
    try {
        ExpressionCompiler compiler = new ExpressionCompiler(ex);
        compiler.compile(ctx);
    } catch (Throwable e) {
        e.printStackTrace();
        fail("Should not raise exception: " + e.getMessage());
    }
}
Also used : ExpressionCompiler(org.mvel2.compiler.ExpressionCompiler)

Example 33 with And

use of org.mvel2.ast.And in project camel by apache.

the class PrepareExampleMojo method executeExamplesReadme.

protected void executeExamplesReadme() throws MojoExecutionException, MojoFailureException {
    Set<File> examples = new TreeSet<>();
    // only run in examples directory where the main readme.adoc file is located
    String currentDir = Paths.get(".").normalize().toAbsolutePath().toString();
    if (!currentDir.endsWith("examples")) {
        return;
    }
    File dir = new File(".");
    File[] files = dir.listFiles();
    if (files != null) {
        examples.addAll(Arrays.asList(files));
    }
    try {
        List<ExampleModel> models = new ArrayList<>();
        for (File file : examples) {
            if (file.isDirectory() && file.getName().startsWith("camel-example")) {
                File pom = new File(file, "pom.xml");
                String existing = FileUtils.readFileToString(pom);
                ExampleModel model = new ExampleModel();
                model.setFileName(file.getName());
                String name = StringHelper.between(existing, "<name>", "</name>");
                String title = StringHelper.between(existing, "<title>", "</title>");
                String description = StringHelper.between(existing, "<description>", "</description>");
                String category = StringHelper.between(existing, "<category>", "</category>");
                if (title != null) {
                    model.setTitle(title);
                } else {
                    // fallback and use file name as title
                    model.setTitle(asTitle(file.getName()));
                }
                if (description != null) {
                    model.setDescription(description);
                }
                if (category != null) {
                    model.setCategory(category);
                }
                if (name != null && name.contains("(deprecated)")) {
                    model.setDeprecated("true");
                } else {
                    model.setDeprecated("false");
                }
                // readme files is either readme.md or readme.adoc
                String[] readmes = new File(file, ".").list((folder, fileName) -> fileName.toLowerCase().startsWith("readme"));
                if (readmes != null && readmes.length == 1) {
                    model.setReadmeFileName(readmes[0]);
                }
                models.add(model);
            }
        }
        // sort the models
        Collections.sort(models, new ExampleComparator());
        // how many deprecated
        long deprecated = models.stream().filter(m -> "true".equals(m.getDeprecated())).count();
        // update the big readme file in the examples dir
        File file = new File(".", "README.adoc");
        // update regular components
        boolean exists = file.exists();
        String changed = templateExamples(models, deprecated);
        boolean updated = updateExamples(file, changed);
        if (updated) {
            getLog().info("Updated readme.adoc file: " + file);
        } else if (exists) {
            getLog().debug("No changes to readme.adoc file: " + file);
        } else {
            getLog().warn("No readme.adoc file: " + file);
        }
    } catch (IOException e) {
        throw new MojoFailureException("Error due " + e.getMessage(), e);
    }
}
Also used : Arrays(java.util.Arrays) PackageHelper.writeText(org.apache.camel.maven.packaging.PackageHelper.writeText) MavenProjectHelper(org.apache.maven.project.MavenProjectHelper) Set(java.util.Set) IOException(java.io.IOException) HashMap(java.util.HashMap) FileUtils(org.apache.commons.io.FileUtils) FileInputStream(java.io.FileInputStream) TemplateRuntime(org.mvel2.templates.TemplateRuntime) MojoExecutionException(org.apache.maven.plugin.MojoExecutionException) File(java.io.File) TreeSet(java.util.TreeSet) Collections(edu.emory.mathcs.backport.java.util.Collections) ArrayList(java.util.ArrayList) MojoFailureException(org.apache.maven.plugin.MojoFailureException) List(java.util.List) Paths(java.nio.file.Paths) MavenProject(org.apache.maven.project.MavenProject) PackageHelper.loadText(org.apache.camel.maven.packaging.PackageHelper.loadText) Map(java.util.Map) Comparator(java.util.Comparator) ExampleModel(org.apache.camel.maven.packaging.model.ExampleModel) AbstractMojo(org.apache.maven.plugin.AbstractMojo) ExampleModel(org.apache.camel.maven.packaging.model.ExampleModel) ArrayList(java.util.ArrayList) MojoFailureException(org.apache.maven.plugin.MojoFailureException) IOException(java.io.IOException) TreeSet(java.util.TreeSet) File(java.io.File)

Example 34 with And

use of org.mvel2.ast.And in project mvel by mvel.

the class CompilerTools method finalizePayload.

/**
 * Finalize the payload, by reducing any stack-based-operations to dedicated nodes where possible.
 *
 * @param astLinkedList          - AST to be optimized.
 * @param secondPassOptimization - perform a second pass optimization to optimize boolean expressions.
 * @param pCtx                    - The parser context
 * @return optimized AST
 */
public static ASTLinkedList finalizePayload(ASTLinkedList astLinkedList, boolean secondPassOptimization, ParserContext pCtx) {
    ASTLinkedList optimizedAst = new ASTLinkedList();
    ASTNode tk, tkOp, tkOp2;
    /**
     * Re-process the AST and optimize it.
     */
    while (astLinkedList.hasMoreNodes()) {
        if ((tk = astLinkedList.nextNode()).getFields() == -1) {
            optimizedAst.addTokenNode(tk);
        } else if (astLinkedList.hasMoreNodes()) {
            if ((tkOp = astLinkedList.nextNode()).getFields() == -1) {
                optimizedAst.addTokenNode(tk, tkOp);
            } else if (tkOp.isOperator() && tkOp.getOperator() < 21) {
                int op = tkOp.getOperator();
                int op2;
                if (op == -1) {
                    throw new CompileException("illegal use of operator: " + tkOp.getName(), tkOp.getExpr(), tk.getStart());
                }
                ASTNode tk2 = astLinkedList.nextNode();
                BinaryOperation bo;
                if (tk.getEgressType() == Integer.class && tk2.getEgressType() == Integer.class) {
                    bo = boOptimize(op, tk, tk2, pCtx);
                } else {
                    /**
                     * Let's see if we can simply the expression more.
                     */
                    bo = null;
                    boolean inv = tkOp.isOperator(Operator.SUB);
                    boolean reduc = isReductionOpportunity(tkOp, tk2);
                    boolean p_inv = false;
                    while (reduc) {
                        ASTNode oper = astLinkedList.nextNode();
                        ASTNode rightNode = astLinkedList.nextNode();
                        if (rightNode == null)
                            break;
                        Object val = new BinaryOperation(oper.getOperator(), inv ? new LiteralNode(signNumber(tk2.getLiteralValue()), pCtx) : tk2, rightNode, pCtx).getReducedValueAccelerated(null, null, null);
                        if (!astLinkedList.hasMoreNodes() && BlankLiteral.INSTANCE.equals(val)) {
                            optimizedAst.addTokenNode(tk);
                            continue;
                        }
                        reduc = astLinkedList.hasMoreNodes() && (reducacbleOperator(astLinkedList.peekNode().getOperator())) && astLinkedList.peekNext().isLiteral();
                        if (inv)
                            p_inv = true;
                        inv = false;
                        if (!reduc) {
                            bo = new BinaryOperation(tkOp.getOperator(), tk, new LiteralNode(p_inv ? signNumber(val) : val, pCtx), pCtx);
                        } else {
                            tk2 = new LiteralNode(val, pCtx);
                        }
                    }
                    if (bo == null)
                        bo = new BinaryOperation(op, tk, tk2, pCtx);
                }
                tkOp2 = null;
                /**
                 * If we have a chain of math/comparitive operators then we fill them into the tree
                 * right here.
                 */
                while (astLinkedList.hasMoreNodes() && (tkOp2 = astLinkedList.nextNode()).isOperator() && tkOp2.getFields() != -1 && (op2 = tkOp2.getOperator()) != -1 && op2 < 21) {
                    if (PTABLE[op2] > PTABLE[op]) {
                        // bo.setRightMost(new BinaryOperation(op2, bo.getRightMost(), astLinkedList.nextNode(), pCtx));
                        bo.setRightMost(boOptimize(op2, bo.getRightMost(), astLinkedList.nextNode(), pCtx));
                    } else if (bo.getOperation() != op2 && PTABLE[op] == PTABLE[op2]) {
                        if (PTABLE[bo.getOperation()] == PTABLE[op2]) {
                            // bo = new BinaryOperation(op2, bo, astLinkedList.nextNode(), pCtx);
                            bo = boOptimize(op2, bo, astLinkedList.nextNode(), pCtx);
                        } else {
                            tk2 = astLinkedList.nextNode();
                            if (isIntOptimizationviolation(bo, tk2)) {
                                bo = new BinaryOperation(bo.getOperation(), bo.getLeft(), bo.getRight(), pCtx);
                            }
                            bo.setRight(new BinaryOperation(op2, bo.getRight(), tk2, pCtx));
                        }
                    } else if (PTABLE[bo.getOperation()] >= PTABLE[op2]) {
                        bo = new BinaryOperation(op2, bo, astLinkedList.nextNode(), pCtx);
                    } else {
                        tk2 = astLinkedList.nextNode();
                        if (isIntOptimizationviolation(bo, tk2)) {
                            bo = new BinaryOperation(bo.getOperation(), bo.getLeft(), bo.getRight(), pCtx);
                        }
                        bo.setRight(new BinaryOperation(op2, bo.getRight(), tk2, pCtx));
                    }
                    op = op2;
                    tkOp = tkOp2;
                }
                if (tkOp2 != null && tkOp2 != tkOp) {
                    optimizeOperator(tkOp2.getOperator(), bo, tkOp2, astLinkedList, optimizedAst, pCtx);
                } else {
                    optimizedAst.addTokenNode(bo);
                }
            } else if (tkOp.isOperator()) {
                optimizeOperator(tkOp.getOperator(), tk, tkOp, astLinkedList, optimizedAst, pCtx);
            } else if (!tkOp.isAssignment() && !tkOp.isOperator() && tk.getLiteralValue() instanceof Class) {
                optimizedAst.addTokenNode(new DeclTypedVarNode(tkOp.getName(), tkOp.getExpr(), tkOp.getStart(), tk.getOffset(), (Class) tk.getLiteralValue(), 0, pCtx));
            } else if (tkOp.isAssignment() && tk.getLiteralValue() instanceof Class) {
                tk.discard();
                optimizedAst.addTokenNode(tkOp);
            } else if (astLinkedList.hasMoreNodes() && tkOp.getLiteralValue() instanceof Class && astLinkedList.peekNode().isAssignment()) {
                tkOp.discard();
                optimizedAst.addTokenNode(tk, astLinkedList.nextNode());
            } else {
                astLinkedList.back();
                optimizedAst.addTokenNode(tk);
            }
        } else {
            optimizedAst.addTokenNode(tk);
        }
    }
    if (secondPassOptimization) {
        /**
         * Perform a second pass optimization for boolean conditions.
         */
        (astLinkedList = optimizedAst).reset();
        optimizedAst = new ASTLinkedList();
        while (astLinkedList.hasMoreNodes()) {
            if ((tk = astLinkedList.nextNode()).getFields() == -1) {
                optimizedAst.addTokenNode(tk);
            } else if (astLinkedList.hasMoreNodes()) {
                if ((tkOp = astLinkedList.nextNode()).getFields() == -1) {
                    optimizedAst.addTokenNode(tk, tkOp);
                } else if (tkOp.isOperator() && (tkOp.getOperator() == Operator.AND || tkOp.getOperator() == Operator.OR)) {
                    tkOp2 = null;
                    BooleanNode bool;
                    if (tkOp.getOperator() == Operator.AND) {
                        bool = new And(tk, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                    } else {
                        bool = new Or(tk, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                    }
                    while (astLinkedList.hasMoreNodes() && (tkOp2 = astLinkedList.nextNode()).isOperator() && (tkOp2.isOperator(Operator.AND) || tkOp2.isOperator(Operator.OR))) {
                        if ((tkOp = tkOp2).getOperator() == Operator.AND) {
                            bool.setRightMost(new And(bool.getRightMost(), astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx));
                        } else {
                            bool = new Or(bool, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                        }
                    }
                    optimizedAst.addTokenNode(bool);
                    if (tkOp2 != null && tkOp2 != tkOp) {
                        optimizedAst.addTokenNode(tkOp2);
                    }
                } else {
                    optimizedAst.addTokenNode(tk, tkOp);
                }
            } else {
                optimizedAst.addTokenNode(tk);
            }
        }
    }
    return optimizedAst;
}
Also used : Or(org.mvel2.ast.Or) BinaryOperation(org.mvel2.ast.BinaryOperation) BooleanNode(org.mvel2.ast.BooleanNode) LiteralNode(org.mvel2.ast.LiteralNode) And(org.mvel2.ast.And) DeclTypedVarNode(org.mvel2.ast.DeclTypedVarNode) ASTNode(org.mvel2.ast.ASTNode) CompileException(org.mvel2.CompileException)

Example 35 with And

use of org.mvel2.ast.And in project mvel by mvel.

the class ParseTools method handleEscapeSequence.

/**
 * Replace escape sequences and return trim required.
 *
 * @param escapeStr -
 * @param pos       -
 * @return -
 */
public static int handleEscapeSequence(char[] escapeStr, int pos) {
    escapeStr[pos - 1] = 0;
    switch(escapeStr[pos]) {
        case '\\':
            escapeStr[pos] = '\\';
            return 1;
        case 'b':
            escapeStr[pos] = '\b';
            return 1;
        case 'f':
            escapeStr[pos] = '\f';
            return 1;
        case 't':
            escapeStr[pos] = '\t';
            return 1;
        case 'r':
            escapeStr[pos] = '\r';
            return 1;
        case 'n':
            escapeStr[pos] = '\n';
            return 1;
        case '\'':
            escapeStr[pos] = '\'';
            return 1;
        case '"':
            escapeStr[pos] = '\"';
            return 1;
        case 'u':
            // unicode
            int s = pos;
            if (s + 4 > escapeStr.length)
                throw new CompileException("illegal unicode escape sequence", escapeStr, pos);
            else {
                while (++pos - s != 5) {
                    if ((escapeStr[pos] > ('0' - 1) && escapeStr[pos] < ('9' + 1)) || (escapeStr[pos] > ('A' - 1) && escapeStr[pos] < ('F' + 1))) {
                    } else {
                        throw new CompileException("illegal unicode escape sequence", escapeStr, pos);
                    }
                }
                escapeStr[s - 1] = (char) Integer.decode("0x" + new String(escapeStr, s + 1, 4)).intValue();
                escapeStr[s] = 0;
                escapeStr[s + 1] = 0;
                escapeStr[s + 2] = 0;
                escapeStr[s + 3] = 0;
                escapeStr[s + 4] = 0;
                return 5;
            }
        default:
            // octal
            s = pos;
            while (escapeStr[pos] >= '0' && escapeStr[pos] < '8') {
                if (pos != s && escapeStr[s] > '3') {
                    escapeStr[s - 1] = (char) Integer.decode("0" + new String(escapeStr, s, pos - s + 1)).intValue();
                    escapeStr[s] = 0;
                    escapeStr[s + 1] = 0;
                    return 2;
                } else if ((pos - s) == 2) {
                    escapeStr[s - 1] = (char) Integer.decode("0" + new String(escapeStr, s, pos - s + 1)).intValue();
                    escapeStr[s] = 0;
                    escapeStr[s + 1] = 0;
                    escapeStr[s + 2] = 0;
                    return 3;
                }
                if (pos + 1 == escapeStr.length || (escapeStr[pos] < '0' || escapeStr[pos] > '7')) {
                    escapeStr[s - 1] = (char) Integer.decode("0" + new String(escapeStr, s, pos - s + 1)).intValue();
                    escapeStr[s] = 0;
                    return 1;
                }
                pos++;
            }
            throw new CompileException("illegal escape sequence: " + escapeStr[pos], escapeStr, pos);
    }
}
Also used : CompileException(org.mvel2.CompileException)

Aggregations

CompileException (org.mvel2.CompileException)22 HashMap (java.util.HashMap)13 Map (java.util.Map)12 ParserContext (org.mvel2.ParserContext)12 ASTNode (org.mvel2.ast.ASTNode)9 Type (org.mvel2.asm.Type)8 Serializable (java.io.Serializable)7 Method (java.lang.reflect.Method)7 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)7 ExpressionCompiler (org.mvel2.compiler.ExpressionCompiler)7 StringAppender (org.mvel2.util.StringAppender)6 EndOfStatement (org.mvel2.ast.EndOfStatement)5 IOException (java.io.IOException)4 BitSet (java.util.BitSet)4 List (java.util.List)4 LabelNode (org.mvel2.asm.tree.LabelNode)4 LiteralNode (org.mvel2.ast.LiteralNode)4 Proto (org.mvel2.ast.Proto)4 ArrayList (java.util.ArrayList)3 Money (org.broadleafcommerce.common.money.Money)3