Search in sources :

Example 1 with SimpleNode

use of org.apache.camel.language.simple.ast.SimpleNode 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 2 with SimpleNode

use of org.apache.camel.language.simple.ast.SimpleNode in project camel by apache.

the class SimpleExpressionParser method parseAndCreateAstModel.

protected void parseAndCreateAstModel() {
    // we loop the tokens and create a sequence of ast nodes
    // counter to keep track of number of functions in the tokens
    AtomicInteger functions = new AtomicInteger();
    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, functions);
        if (node != null) {
            // 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);
    }
}
Also used : LiteralNode(org.apache.camel.language.simple.ast.LiteralNode) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) LiteralExpression(org.apache.camel.language.simple.ast.LiteralExpression) SimpleToken(org.apache.camel.language.simple.types.SimpleToken) SimpleNode(org.apache.camel.language.simple.ast.SimpleNode)

Example 3 with SimpleNode

use of org.apache.camel.language.simple.ast.SimpleNode 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 4 with SimpleNode

use of org.apache.camel.language.simple.ast.SimpleNode 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)

Example 5 with SimpleNode

use of org.apache.camel.language.simple.ast.SimpleNode in project camel by apache.

the class SimplePredicateParser method prepareBinaryExpressions.

/**
     * Prepares binary expressions.
     * <p/>
     * This process prepares the binary expressions in the AST. This is done
     * by linking the binary 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 prepareBinaryExpressions() {
    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 BinaryExpression) {
            BinaryExpression binary = (BinaryExpression) token;
            // remember the binary operator
            String operator = binary.getOperator().toString();
            if (left == null) {
                throw new SimpleParserException("Binary operator " + operator + " has no left hand side token", token.getToken().getIndex());
            }
            if (!binary.acceptLeftNode(left)) {
                throw new SimpleParserException("Binary operator " + operator + " does not support left hand side token " + left.getToken(), token.getToken().getIndex());
            }
            if (right == null) {
                throw new SimpleParserException("Binary operator " + operator + " has no right hand side token", token.getToken().getIndex());
            }
            if (!binary.acceptRightNode(right)) {
                throw new SimpleParserException("Binary operator " + operator + " does not support right hand side token " + right.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) BinaryExpression(org.apache.camel.language.simple.ast.BinaryExpression) Stack(java.util.Stack) SimpleNode(org.apache.camel.language.simple.ast.SimpleNode)

Aggregations

SimpleNode (org.apache.camel.language.simple.ast.SimpleNode)8 SimpleParserException (org.apache.camel.language.simple.types.SimpleParserException)5 Stack (java.util.Stack)4 BinaryExpression (org.apache.camel.language.simple.ast.BinaryExpression)3 LiteralExpression (org.apache.camel.language.simple.ast.LiteralExpression)3 LogicalExpression (org.apache.camel.language.simple.ast.LogicalExpression)3 UnaryExpression (org.apache.camel.language.simple.ast.UnaryExpression)3 ArrayList (java.util.ArrayList)2 DoubleQuoteStart (org.apache.camel.language.simple.ast.DoubleQuoteStart)2 LiteralNode (org.apache.camel.language.simple.ast.LiteralNode)2 NullExpression (org.apache.camel.language.simple.ast.NullExpression)2 SimpleFunctionStart (org.apache.camel.language.simple.ast.SimpleFunctionStart)2 SingleQuoteStart (org.apache.camel.language.simple.ast.SingleQuoteStart)2 SimpleToken (org.apache.camel.language.simple.types.SimpleToken)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 Expression (org.apache.camel.Expression)1 Predicate (org.apache.camel.Predicate)1 Block (org.apache.camel.language.simple.ast.Block)1 BlockEnd (org.apache.camel.language.simple.ast.BlockEnd)1