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());
}
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;
}
};
}
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);
}
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);
}
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);
}
}
Aggregations