@Nullable private SpelNodeImpl eatPrimaryExpression() { SpelNodeImpl start = eatStartNode(); // always a start node List<SpelNodeImpl> nodes = null; SpelNodeImpl node = eatNode(); while (node != null) { if (nodes == null) { nodes = new ArrayList<>(4); nodes.add(start); } nodes.add(node); node = eatNode(); } if (start == null || nodes == null) { return start; } return new CompoundExpression(start.getStartPosition(), nodes.get(nodes.size() - 1).getEndPosition(), nodes.toArray(new SpelNodeImpl[0])); }
/** * Eat an identifier, possibly qualified (meaning that it is dotted). * TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c) */ private SpelNodeImpl eatPossiblyQualifiedId() { Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Token node = peekToken(); while (isValidQualifiedId(node)) { nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), node.startPos, node.endPos)); } node = peekToken(); } if (qualifiedIdPieces.isEmpty()) { if (node == null) { throw internalException( this.expressionString.length(), SpelMessage.OOD); } throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } return new QualifiedIdentifier(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition(), qualifiedIdPieces.toArray(new SpelNodeImpl[0])); }
@Nullable private SpelNodeImpl eatPrimaryExpression() { SpelNodeImpl start = eatStartNode(); // always a start node List<SpelNodeImpl> nodes = null; SpelNodeImpl node = eatNode(); while (node != null) { if (nodes == null) { nodes = new ArrayList<>(4); nodes.add(start); } nodes.add(node); node = eatNode(); } if (start == null || nodes == null) { return start; } return new CompoundExpression(toPos(start.getStartPosition(), nodes.get(nodes.size() - 1).getEndPosition()), nodes.toArray(new SpelNodeImpl[0])); }
/** * Eat an identifier, possibly qualified (meaning that it is dotted). * TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c) */ private SpelNodeImpl eatPossiblyQualifiedId() { Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Token node = peekToken(); while (isValidQualifiedId(node)) { nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), toPos(node))); } node = peekToken(); } if (qualifiedIdPieces.isEmpty()) { if (node == null) { throw internalException( this.expressionString.length(), SpelMessage.OOD); } throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition()); return new QualifiedIdentifier(pos, qualifiedIdPieces.toArray(new SpelNodeImpl[0])); }
@Test public void positionalInformation() { SpelExpression expr = new SpelExpressionParser().parseRaw("true and true or false"); SpelNode rootAst = expr.getAST(); OpOr operatorOr = (OpOr) rootAst; OpAnd operatorAnd = (OpAnd) operatorOr.getLeftOperand(); SpelNode rightOrOperand = operatorOr.getRightOperand(); // check position for final 'false' assertEquals(17, rightOrOperand.getStartPosition()); assertEquals(22, rightOrOperand.getEndPosition()); // check position for first 'true' assertEquals(0, operatorAnd.getLeftOperand().getStartPosition()); assertEquals(4, operatorAnd.getLeftOperand().getEndPosition()); // check position for second 'true' assertEquals(9, operatorAnd.getRightOperand().getStartPosition()); assertEquals(13, operatorAnd.getRightOperand().getEndPosition()); // check position for OperatorAnd assertEquals(5, operatorAnd.getStartPosition()); assertEquals(8, operatorAnd.getEndPosition()); // check position for OperatorOr assertEquals(14, operatorOr.getStartPosition()); assertEquals(16, operatorOr.getEndPosition()); }
@Nullable private SpelNodeImpl eatPrimaryExpression() { SpelNodeImpl start = eatStartNode(); // always a start node List<SpelNodeImpl> nodes = null; SpelNodeImpl node = eatNode(); while (node != null) { if (nodes == null) { nodes = new ArrayList<>(4); nodes.add(start); } nodes.add(node); node = eatNode(); } if (start == null || nodes == null) { return start; } return new CompoundExpression(toPos(start.getStartPosition(), nodes.get(nodes.size() - 1).getEndPosition()), nodes.toArray(new SpelNodeImpl[0])); }
/** * Eat an identifier, possibly qualified (meaning that it is dotted). * TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c) */ private SpelNodeImpl eatPossiblyQualifiedId() { Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Token node = peekToken(); while (isValidQualifiedId(node)) { nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), toPos(node))); } node = peekToken(); } if (qualifiedIdPieces.isEmpty()) { if (node == null) { throw internalException( this.expressionString.length(), SpelMessage.OOD); } throw internalException(node.startPos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } int pos = toPos(qualifiedIdPieces.getFirst().getStartPosition(), qualifiedIdPieces.getLast().getEndPosition()); return new QualifiedIdentifier(pos, qualifiedIdPieces.toArray(new SpelNodeImpl[0])); }