Search in sources :

Example 6 with Or

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

the class AbstractParser method procTypedNode.

/**
 * Process the current typed node
 *
 * @param decl node is a declaration or not
 * @return and ast node
 */
private ASTNode procTypedNode(boolean decl) {
    while (true) {
        if (lastNode.getLiteralValue() instanceof String) {
            char[] tmp = ((String) lastNode.getLiteralValue()).toCharArray();
            TypeDescriptor tDescr = new TypeDescriptor(tmp, 0, tmp.length, 0);
            try {
                lastNode.setLiteralValue(getClassReference(pCtx, tDescr));
                lastNode.discard();
            } catch (Exception e) {
            // fall through;
            }
        }
        if (lastNode.isLiteral() && lastNode.getLiteralValue() instanceof Class) {
            lastNode.discard();
            captureToEOS();
            if (decl) {
                splitAccumulator.add(new DeclTypedVarNode(new String(expr, st, cursor - st), expr, st, cursor - st, (Class) lastNode.getLiteralValue(), fields | ASTNode.ASSIGN, pCtx));
            } else {
                captureToEOS();
                splitAccumulator.add(new TypedVarNode(expr, st, cursor - st - 1, fields | ASTNode.ASSIGN, (Class) lastNode.getLiteralValue(), pCtx));
            }
        } else if (lastNode instanceof Proto) {
            captureToEOS();
            if (decl) {
                splitAccumulator.add(new DeclProtoVarNode(new String(expr, st, cursor - st), (Proto) lastNode, fields | ASTNode.ASSIGN, pCtx));
            } else {
                splitAccumulator.add(new ProtoVarNode(expr, st, cursor - st, fields | ASTNode.ASSIGN, (Proto) lastNode, pCtx));
            }
        } else // this redundant looking code is needed to work with the interpreter and MVELSH properly.
        if ((fields & ASTNode.COMPILE_IMMEDIATE) == 0) {
            if (stk.peek() instanceof Class) {
                captureToEOS();
                if (decl) {
                    splitAccumulator.add(new DeclTypedVarNode(new String(expr, st, cursor - st), expr, st, cursor - st, (Class) stk.pop(), fields | ASTNode.ASSIGN, pCtx));
                } else {
                    splitAccumulator.add(new TypedVarNode(expr, st, cursor - st, fields | ASTNode.ASSIGN, (Class) stk.pop(), pCtx));
                }
            } else if (stk.peek() instanceof Proto) {
                captureToEOS();
                if (decl) {
                    splitAccumulator.add(new DeclProtoVarNode(new String(expr, st, cursor - st), (Proto) stk.pop(), fields | ASTNode.ASSIGN, pCtx));
                } else {
                    splitAccumulator.add(new ProtoVarNode(expr, st, cursor - st, fields | ASTNode.ASSIGN, (Proto) stk.pop(), pCtx));
                }
            } else {
                throw new CompileException("unknown class or illegal statement: " + lastNode.getLiteralValue(), expr, cursor);
            }
        } else {
            throw new CompileException("unknown class or illegal statement: " + lastNode.getLiteralValue(), expr, cursor);
        }
        skipWhitespace();
        if (cursor < end && expr[cursor] == ',') {
            st = ++cursor;
            splitAccumulator.add(new EndOfStatement());
        } else {
            return (ASTNode) splitAccumulator.pop();
        }
    }
}
Also used : CompileException(org.mvel2.CompileException) CompileException(org.mvel2.CompileException)

Example 7 with Or

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

the class ReflectiveAccessorOptimizer method getCollectionProperty.

/**
 * Handle accessing a property embedded in a collections, map, or array
 *
 * @param ctx  -
 * @param prop -
 * @return -
 * @throws Exception -
 */
private Object getCollectionProperty(Object ctx, String prop) throws Exception {
    if (prop.length() > 0) {
        ctx = getBeanProperty(ctx, prop);
    }
    if (ctx == null)
        return null;
    int start = ++cursor;
    skipWhitespace();
    if (cursor == end)
        throw new CompileException("unterminated '['", this.expr, this.start);
    String item;
    if (scanTo(']'))
        throw new CompileException("unterminated '['", this.expr, this.start);
    item = new String(expr, start, cursor - start);
    boolean itemSubExpr = true;
    Object idx = null;
    try {
        idx = parseInt(item);
        itemSubExpr = false;
    } catch (Exception e) {
    // not a number;
    }
    ExecutableStatement itemStmt = null;
    if (itemSubExpr) {
        try {
            idx = (itemStmt = (ExecutableStatement) subCompileExpression(item.toCharArray(), pCtx)).getValue(ctx, thisRef, variableFactory);
        } catch (CompileException e) {
            e.setExpr(this.expr);
            e.setCursor(start);
            throw e;
        }
    }
    ++cursor;
    if (ctx instanceof Map) {
        if (itemSubExpr) {
            addAccessorNode(new MapAccessorNest(itemStmt, null));
        } else {
            addAccessorNode(new MapAccessor(parseInt(item)));
        }
        return ((Map) ctx).get(idx);
    } else if (ctx instanceof List) {
        if (itemSubExpr) {
            addAccessorNode(new ListAccessorNest(itemStmt, null));
        } else {
            addAccessorNode(new ListAccessor(parseInt(item)));
        }
        return ((List) ctx).get((Integer) idx);
    } else if (ctx.getClass().isArray()) {
        if (itemSubExpr) {
            addAccessorNode(new ArrayAccessorNest(itemStmt));
        } else {
            addAccessorNode(new ArrayAccessor(parseInt(item)));
        }
        return Array.get(ctx, (Integer) idx);
    } else if (ctx instanceof CharSequence) {
        if (itemSubExpr) {
            addAccessorNode(new IndexedCharSeqAccessorNest(itemStmt));
        } else {
            addAccessorNode(new IndexedCharSeqAccessor(parseInt(item)));
        }
        return ((CharSequence) ctx).charAt((Integer) idx);
    } else {
        TypeDescriptor tDescr = new TypeDescriptor(expr, this.start, length, 0);
        if (tDescr.isArray()) {
            Class cls = getClassReference((Class) ctx, tDescr, variableFactory, pCtx);
            rootNode = new StaticReferenceAccessor(cls);
            return cls;
        }
        throw new CompileException("illegal use of []: unknown type: " + ctx.getClass().getName(), this.expr, this.start);
    }
}
Also used : ExecutableStatement(org.mvel2.compiler.ExecutableStatement) TypeDescriptor(org.mvel2.ast.TypeDescriptor) List(java.util.List) Map(java.util.Map) WeakHashMap(java.util.WeakHashMap)

Example 8 with Or

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

the class ConditionAnalyzer method analyzeCondition.

private Condition analyzeCondition(ASTNode node) {
    boolean isNegated = false;
    if (node instanceof Negation) {
        isNegated = true;
        ExecutableStatement statement = ((Negation) node).getStatement();
        if (statement instanceof ExecutableLiteral) {
            return new FixedValueCondition(!(Boolean) ((ExecutableLiteral) statement).getLiteral());
        }
        node = ((ExecutableAccessor) statement).getNode();
    }
    node = analyzeSubstatement(node);
    if (node instanceof LiteralNode && node.getEgressType() == Boolean.class) {
        boolean literalValue = (Boolean) node.getLiteralValue();
        return new FixedValueCondition(isNegated ? !literalValue : literalValue);
    }
    if (node instanceof Negation) {
        isNegated = !isNegated;
        node = ((ExecutableAccessor) ((Negation) node).getStatement()).getNode();
        node = analyzeSubstatement(node);
    }
    if (node instanceof And || node instanceof Or) {
        return analyzeCombinedCondition((BooleanNode) node, isNegated);
    }
    return analyzeSingleCondition(node, isNegated);
}
Also used : LiteralNode(org.mvel2.ast.LiteralNode) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) Or(org.mvel2.ast.Or) Negation(org.mvel2.ast.Negation) And(org.mvel2.ast.And) ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral)

Example 9 with Or

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

the class MVELInterpretedRuntime method parseAndExecuteInterpreted.

/**
 * Main interpreter loop.
 *
 * @return value
 */
private Object parseAndExecuteInterpreted() {
    ASTNode tk = null;
    int operator;
    lastWasIdentifier = false;
    try {
        while ((tk = nextToken()) != null) {
            holdOverRegister = null;
            if (lastWasIdentifier && lastNode.isDiscard()) {
                stk.discard();
            }
            /**
             * If we are at the beginning of a statement, then we immediately push the first token
             * onto the stack.
             */
            if (stk.isEmpty()) {
                stk.push(tk.getReducedValue(ctx, ctx, variableFactory));
                /**
                 * If this is a substatement, we need to move the result into the d-stack to preserve
                 * proper execution order.
                 */
                if (tk instanceof Substatement && (tk = nextToken()) != null) {
                    if (isArithmeticOperator(operator = tk.getOperator())) {
                        stk.push(nextToken().getReducedValue(ctx, ctx, variableFactory), operator);
                        if (procBooleanOperator(arithmeticFunctionReduction(operator)) == -1)
                            return stk.peek();
                        else
                            continue;
                    }
                } else {
                    continue;
                }
            }
            if (variableFactory.tiltFlag()) {
                return stk.pop();
            }
            switch(procBooleanOperator(operator = tk.getOperator())) {
                case RETURN:
                    variableFactory.setTiltFlag(true);
                    return stk.pop();
                case OP_TERMINATE:
                    return stk.peek();
                case OP_RESET_FRAME:
                    continue;
                case OP_OVERFLOW:
                    if (!tk.isOperator()) {
                        if (!(stk.peek() instanceof Class)) {
                            throw new CompileException("unexpected token or unknown identifier:" + tk.getName(), expr, st);
                        }
                        variableFactory.createVariable(tk.getName(), null, (Class) stk.peek());
                    }
                    continue;
            }
            stk.push(nextToken().getReducedValue(ctx, ctx, variableFactory), operator);
            switch((operator = arithmeticFunctionReduction(operator))) {
                case OP_TERMINATE:
                    return stk.peek();
                case OP_RESET_FRAME:
                    continue;
            }
            if (procBooleanOperator(operator) == OP_TERMINATE)
                return stk.peek();
        }
        if (holdOverRegister != null) {
            return holdOverRegister;
        }
    } catch (CompileException e) {
        throw ErrorUtil.rewriteIfNeeded(e, expr, start);
    } catch (NullPointerException e) {
        if (tk != null && tk.isOperator()) {
            CompileException ce = new CompileException("incomplete statement: " + tk.getName() + " (possible use of reserved keyword as identifier: " + tk.getName() + ")", expr, st, e);
            ce.setExpr(expr);
            ce.setLineNumber(line);
            ce.setCursor(cursor);
            throw ce;
        } else {
            throw e;
        }
    }
    return stk.peek();
}
Also used : ASTNode(org.mvel2.ast.ASTNode) Substatement(org.mvel2.ast.Substatement)

Example 10 with Or

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

the class MVELRuntime method execute.

/**
 * Main interpreter.
 *
 * @param debugger        Run in debug mode
 * @param expression      The compiled expression object
 * @param ctx             The root context object
 * @param variableFactory The variable factory to be injected
 * @return The resultant value
 * @see org.mvel2.MVEL
 */
public static Object execute(boolean debugger, final CompiledExpression expression, final Object ctx, VariableResolverFactory variableFactory) {
    Object v1, v2;
    ExecutionStack stk = new ExecutionStack();
    variableFactory.setTiltFlag(false);
    ASTNode tk = expression.getFirstNode();
    Integer operator;
    if (tk == null)
        return null;
    try {
        do {
            if (tk.fields == -1) {
                /**
                 * This may seem silly and redundant, however, when an MVEL script recurses into a block
                 * or substatement, a new runtime loop is entered.   Since the debugger state is not
                 * passed through the AST, it is not possible to forward the state directly.  So when we
                 * encounter a debugging symbol, we check the thread local to see if there is are registered
                 * breakpoints.  If we find them, we assume that we are debugging.
                 *
                 * The consequence of this of course, is that it's not ideal to compileShared expressions with
                 * debugging symbols which you plan to use in a production enviroment.
                 */
                if (debugger || (debugger = hasDebuggerContext())) {
                    try {
                        debuggerContext.get().checkBreak((LineLabel) tk, variableFactory, expression);
                    } catch (NullPointerException e) {
                    // do nothing for now.  this isn't as calus as it seems.
                    }
                }
                continue;
            } else if (stk.isEmpty()) {
                stk.push(tk.getReducedValueAccelerated(ctx, ctx, variableFactory));
            }
            if (variableFactory.tiltFlag()) {
                return stk.pop();
            }
            switch(operator = tk.getOperator()) {
                case RETURN:
                    variableFactory.setTiltFlag(true);
                    return stk.pop();
                case NOOP:
                    continue;
                case TERNARY:
                    if (!stk.popBoolean()) {
                        // noinspection StatementWithEmptyBody
                        while (tk.nextASTNode != null && !(tk = tk.nextASTNode).isOperator(TERNARY_ELSE)) ;
                    }
                    stk.clear();
                    continue;
                case TERNARY_ELSE:
                    return stk.pop();
                case END_OF_STMT:
                    /**
                     * If the program doesn't end here then we wipe anything off the stack that remains.
                     * Althought it may seem like intuitive stack optimizations could be leveraged by
                     * leaving hanging values on the stack,  trust me it's not a good idea.
                     */
                    if (tk.nextASTNode != null) {
                        stk.clear();
                    }
                    continue;
            }
            stk.push(tk.nextASTNode.getReducedValueAccelerated(ctx, ctx, variableFactory), operator);
            try {
                while (stk.isReduceable()) {
                    if ((Integer) stk.peek() == CHOR) {
                        stk.pop();
                        v1 = stk.pop();
                        v2 = stk.pop();
                        if (!isEmpty(v2) || !isEmpty(v1)) {
                            stk.clear();
                            stk.push(!isEmpty(v2) ? v2 : v1);
                        } else
                            stk.push(null);
                    } else {
                        stk.op();
                    }
                }
            } catch (ClassCastException e) {
                throw new CompileException("syntax error or incomptable types", new char[0], 0, e);
            } catch (CompileException e) {
                throw e;
            } catch (Exception e) {
                throw new CompileException("failed to compileShared sub expression", new char[0], 0, e);
            }
        } while ((tk = tk.nextASTNode) != null);
        return stk.peek();
    } catch (NullPointerException e) {
        if (tk != null && tk.isOperator() && tk.nextASTNode != null) {
            throw new CompileException("incomplete statement: " + tk.getName() + " (possible use of reserved keyword as identifier: " + tk.getName() + ")", tk.getExpr(), tk.getStart());
        } else {
            throw e;
        }
    }
}
Also used : ExecutionStack(org.mvel2.util.ExecutionStack) ASTNode(org.mvel2.ast.ASTNode)

Aggregations

CompileException (org.mvel2.CompileException)7 Map (java.util.Map)4 IOException (java.io.IOException)3 ASTNode (org.mvel2.ast.ASTNode)3 Function (org.mvel2.ast.Function)3 HashMap (java.util.HashMap)2 List (java.util.List)2 ParserConfiguration (org.mvel2.ParserConfiguration)2 ParserContext (org.mvel2.ParserContext)2 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)2 StringAppender (org.mvel2.util.StringAppender)2 Collections (edu.emory.mathcs.backport.java.util.Collections)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 Method (java.lang.reflect.Method)1 Paths (java.nio.file.Paths)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 Comparator (java.util.Comparator)1 HashSet (java.util.HashSet)1