Search in sources :

Example 1 with SimpleParserException

use of org.apache.camel.language.simple.types.SimpleParserException in project camel by apache.

the class LogicalExpression method createExpression.

@Override
public Expression createExpression(String expression) {
    ObjectHelper.notNull(left, "left node", this);
    ObjectHelper.notNull(right, "right node", this);
    final Expression leftExp = left.createExpression(expression);
    final Expression rightExp = right.createExpression(expression);
    if (operator == LogicalOperatorType.AND) {
        return createAndExpression(leftExp, rightExp);
    } else if (operator == LogicalOperatorType.OR) {
        return createOrExpression(leftExp, rightExp);
    }
    throw new SimpleParserException("Unknown logical operator " + operator, token.getIndex());
}
Also used : SimpleParserException(org.apache.camel.language.simple.types.SimpleParserException) Expression(org.apache.camel.Expression)

Example 2 with SimpleParserException

use of org.apache.camel.language.simple.types.SimpleParserException in project camel by apache.

the class SimpleFunctionStart method doCreateCompositeExpression.

private Expression doCreateCompositeExpression(final String expression) {
    final SimpleToken token = getToken();
    return new Expression() {

        @Override
        public <T> T evaluate(Exchange exchange, Class<T> type) {
            StringBuilder sb = new StringBuilder();
            boolean quoteEmbeddedFunctions = false;
            // we need to concat the block so we have the expression
            for (SimpleNode child : block.getChildren()) {
                // whether a nested function should be lazy evaluated or not
                boolean lazy = true;
                if (child instanceof SimpleFunctionStart) {
                    lazy = ((SimpleFunctionStart) child).lazyEval(child);
                }
                if (child instanceof LiteralNode) {
                    String text = ((LiteralNode) child).getText();
                    sb.append(text);
                    quoteEmbeddedFunctions |= ((LiteralNode) child).quoteEmbeddedNodes();
                // if its quoted literal then embed that as text
                } else if (!lazy || child instanceof SingleQuoteStart || child instanceof DoubleQuoteStart) {
                    try {
                        // pass in null when we evaluate the nested expressions
                        Expression nested = child.createExpression(null);
                        String text = nested.evaluate(exchange, String.class);
                        if (text != null) {
                            if (quoteEmbeddedFunctions && !StringHelper.isQuoted(text)) {
                                sb.append("'").append(text).append("'");
                            } else {
                                sb.append(text);
                            }
                        }
                    } catch (SimpleParserException e) {
                        // must rethrow parser exception as illegal syntax with details about the location
                        throw new SimpleIllegalSyntaxException(expression, e.getIndex(), e.getMessage(), e);
                    }
                // if its an inlined function then embed that function as text so it can be evaluated lazy
                } else if (child instanceof SimpleFunctionStart) {
                    sb.append(child);
                }
            }
            // we have now concat the block as a String which contains the function expression
            // which we then need to evaluate as a function
            String exp = sb.toString();
            SimpleFunctionExpression function = new SimpleFunctionExpression(token);
            function.addText(exp);
            try {
                return function.createExpression(exp).evaluate(exchange, type);
            } catch (SimpleParserException e) {
                // must rethrow parser exception as illegal syntax with details about the location
                throw new SimpleIllegalSyntaxException(expression, e.getIndex(), e.getMessage(), e);
            }
        }

        @Override
        public String toString() {
            return expression;
        }
    };
}
Also used : SimpleParserException(org.apache.camel.language.simple.types.SimpleParserException) SimpleIllegalSyntaxException(org.apache.camel.language.simple.types.SimpleIllegalSyntaxException) Exchange(org.apache.camel.Exchange) Expression(org.apache.camel.Expression) SimpleToken(org.apache.camel.language.simple.types.SimpleToken)

Example 3 with SimpleParserException

use of org.apache.camel.language.simple.types.SimpleParserException in project camel by apache.

the class BaseSimpleParser method prepareBlocks.

/**
     * Prepares blocks, such as functions, single or double quoted texts.
     * <p/>
     * This process prepares the {@link Block}s in the AST. This is done
     * by linking child {@link SimpleNode nodes} which are within the start and end of the blocks,
     * as child to the given block. This is done to have the AST graph updated and prepared properly.
     * <p/>
     * So when the AST node is later used to create the {@link org.apache.camel.Predicate}s
     * or {@link org.apache.camel.Expression}s to be used by Camel then the AST graph
     * has a linked and prepared graph of nodes which represent the input expression.
     */
protected void prepareBlocks() {
    List<SimpleNode> answer = new ArrayList<SimpleNode>();
    Stack<Block> stack = new Stack<Block>();
    for (SimpleNode token : nodes) {
        if (token instanceof BlockStart) {
            // a new block is started, so push on the stack
            stack.push((Block) token);
        } else if (token instanceof BlockEnd) {
            // end block is just an abstract mode, so we should not add it
            if (stack.isEmpty()) {
                throw new SimpleParserException(token.getToken().getType().getType() + " has no matching start token", token.getToken().getIndex());
            }
            Block top = stack.pop();
            // if there is a block on the stack then it should accept the child token
            Block block = stack.isEmpty() ? null : stack.peek();
            if (block != null) {
                if (!block.acceptAndAddNode(top)) {
                    throw new SimpleParserException(block.getToken().getType() + " cannot accept " + token.getToken().getType(), token.getToken().getIndex());
                }
            } else {
                // no block, so add to answer
                answer.add(top);
            }
        } else {
            // if there is a block on the stack then it should accept the child token
            Block block = stack.isEmpty() ? null : stack.peek();
            if (block != null) {
                if (!block.acceptAndAddNode(token)) {
                    throw new SimpleParserException(block.getToken().getType() + " cannot accept " + token.getToken().getType(), token.getToken().getIndex());
                }
            } else {
                // no block, so add to answer
                answer.add(token);
            }
        }
    }
    // replace nodes from the stack
    nodes.clear();
    nodes.addAll(answer);
}
Also used : SimpleParserException(org.apache.camel.language.simple.types.SimpleParserException) BlockStart(org.apache.camel.language.simple.ast.BlockStart) BlockEnd(org.apache.camel.language.simple.ast.BlockEnd) ArrayList(java.util.ArrayList) Block(org.apache.camel.language.simple.ast.Block) SimpleNode(org.apache.camel.language.simple.ast.SimpleNode) Stack(java.util.Stack)

Example 4 with SimpleParserException

use of org.apache.camel.language.simple.types.SimpleParserException in project camel by apache.

the class SimplePredicateParser method prepareLogicalExpressions.

/**
     * Prepares logical expressions.
     * <p/>
     * This process prepares the logical expressions in the AST. This is done
     * by linking the logical operator with both the right and left hand side
     * nodes, to have the AST graph updated and prepared properly.
     * <p/>
     * So when the AST node is later used to create the {@link Predicate}s
     * to be used by Camel then the AST graph has a linked and prepared
     * graph of nodes which represent the input expression.
     */
private void prepareLogicalExpressions() {
    Stack<SimpleNode> stack = new Stack<SimpleNode>();
    SimpleNode left = null;
    for (int i = 0; i < nodes.size(); i++) {
        if (left == null) {
            left = i > 0 ? nodes.get(i - 1) : null;
        }
        SimpleNode token = nodes.get(i);
        SimpleNode right = i < nodes.size() - 1 ? nodes.get(i + 1) : null;
        if (token instanceof LogicalExpression) {
            LogicalExpression logical = (LogicalExpression) token;
            // remember the logical operator
            String operator = logical.getOperator().toString();
            if (left == null) {
                throw new SimpleParserException("Logical operator " + operator + " has no left hand side token", token.getToken().getIndex());
            }
            if (!logical.acceptLeftNode(left)) {
                throw new SimpleParserException("Logical operator " + operator + " does not support left hand side token " + left.getToken(), token.getToken().getIndex());
            }
            if (right == null) {
                throw new SimpleParserException("Logical operator " + operator + " has no right hand side token", token.getToken().getIndex());
            }
            if (!logical.acceptRightNode(right)) {
                throw new SimpleParserException("Logical operator " + operator + " does not support right hand side token " + left.getToken(), token.getToken().getIndex());
            }
            // pop previous as we need to replace it with this binary operator
            stack.pop();
            stack.push(token);
            // advantage after the right hand side
            i++;
            // this token is now the left for the next loop
            left = token;
        } else {
            // clear left
            left = null;
            stack.push(token);
        }
    }
    nodes.clear();
    nodes.addAll(stack);
}
Also used : SimpleParserException(org.apache.camel.language.simple.types.SimpleParserException) LogicalExpression(org.apache.camel.language.simple.ast.LogicalExpression) Stack(java.util.Stack) SimpleNode(org.apache.camel.language.simple.ast.SimpleNode)

Example 5 with SimpleParserException

use of org.apache.camel.language.simple.types.SimpleParserException in project camel by apache.

the class SimplePredicateParser method parseTokensAndCreateNodes.

/**
     * Parses the tokens and crates the AST nodes.
     * <p/>
     * After the initial parsing of the input (input -> tokens) then we
     * parse again (tokens -> ast).
     * <p/>
     * In this parsing the balance of the blocks is checked, so that each block has a matching
     * start and end token. For example a single quote block, or a function block etc.
     */
protected void parseTokensAndCreateNodes() {
    // we loop the tokens and create a sequence of ast nodes
    // we need to keep a bit of state for keeping track of single and double quotes
    // which need to be balanced and have matching start/end pairs
    SimpleNode lastSingle = null;
    SimpleNode lastDouble = null;
    SimpleNode lastFunction = null;
    AtomicBoolean startSingle = new AtomicBoolean(false);
    AtomicBoolean startDouble = new AtomicBoolean(false);
    AtomicBoolean startFunction = new AtomicBoolean(false);
    LiteralNode imageToken = null;
    for (SimpleToken token : tokens) {
        // break if eol
        if (token.getType().isEol()) {
            break;
        }
        // create a node from the token
        SimpleNode node = createNode(token, startSingle, startDouble, startFunction);
        if (node != null) {
            // keep state of last single/double
            if (node instanceof SingleQuoteStart) {
                lastSingle = node;
            } else if (node instanceof DoubleQuoteStart) {
                lastDouble = node;
            } else if (node instanceof SimpleFunctionStart) {
                lastFunction = node;
            }
            // a new token was created so the current image token need to be added first
            if (imageToken != null) {
                nodes.add(imageToken);
                imageToken = null;
            }
            // and then add the created node
            nodes.add(node);
            // continue to next
            continue;
        }
        // which we need to add together in the same image
        if (imageToken == null) {
            imageToken = new LiteralExpression(token);
        }
        imageToken.addText(token.getText());
    }
    // append any leftover image tokens (when we reached eol)
    if (imageToken != null) {
        nodes.add(imageToken);
    }
    // validate the single, double quote pairs and functions is in balance
    if (startSingle.get()) {
        int index = lastSingle != null ? lastSingle.getToken().getIndex() : 0;
        throw new SimpleParserException("single quote has no ending quote", index);
    }
    if (startDouble.get()) {
        int index = lastDouble != null ? lastDouble.getToken().getIndex() : 0;
        throw new SimpleParserException("double quote has no ending quote", index);
    }
    if (startFunction.get()) {
        // we have a start function, but no ending function
        int index = lastFunction != null ? lastFunction.getToken().getIndex() : 0;
        throw new SimpleParserException("function has no ending token", index);
    }
}
Also used : SimpleParserException(org.apache.camel.language.simple.types.SimpleParserException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) LiteralNode(org.apache.camel.language.simple.ast.LiteralNode) LiteralExpression(org.apache.camel.language.simple.ast.LiteralExpression) DoubleQuoteStart(org.apache.camel.language.simple.ast.DoubleQuoteStart) SingleQuoteStart(org.apache.camel.language.simple.ast.SingleQuoteStart) SimpleToken(org.apache.camel.language.simple.types.SimpleToken) SimpleNode(org.apache.camel.language.simple.ast.SimpleNode) SimpleFunctionStart(org.apache.camel.language.simple.ast.SimpleFunctionStart)

Aggregations

SimpleParserException (org.apache.camel.language.simple.types.SimpleParserException)12 Expression (org.apache.camel.Expression)5 SimpleNode (org.apache.camel.language.simple.ast.SimpleNode)5 Stack (java.util.Stack)4 SimpleToken (org.apache.camel.language.simple.types.SimpleToken)2 ArrayList (java.util.ArrayList)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Exchange (org.apache.camel.Exchange)1 BinaryExpression (org.apache.camel.language.simple.ast.BinaryExpression)1 Block (org.apache.camel.language.simple.ast.Block)1 BlockEnd (org.apache.camel.language.simple.ast.BlockEnd)1 BlockStart (org.apache.camel.language.simple.ast.BlockStart)1 DoubleQuoteStart (org.apache.camel.language.simple.ast.DoubleQuoteStart)1 LiteralExpression (org.apache.camel.language.simple.ast.LiteralExpression)1 LiteralNode (org.apache.camel.language.simple.ast.LiteralNode)1 LogicalExpression (org.apache.camel.language.simple.ast.LogicalExpression)1 SimpleFunctionStart (org.apache.camel.language.simple.ast.SimpleFunctionStart)1 SingleQuoteStart (org.apache.camel.language.simple.ast.SingleQuoteStart)1 UnaryExpression (org.apache.camel.language.simple.ast.UnaryExpression)1 BinaryOperatorType (org.apache.camel.language.simple.types.BinaryOperatorType)1