@Override protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException { return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context); }
private void checkOperands(Token token, @Nullable SpelNodeImpl left, @Nullable SpelNodeImpl right) { checkLeftOperand(token, left); checkRightOperand(token, right); }
@Nullable private SpelNodeImpl eatLogicalOrExpression() { SpelNodeImpl expr = eatLogicalAndExpression(); while (peekIdentifierToken("or") || peekToken(TokenKind.SYMBOLIC_OR)) { Token t = takeToken(); //consume OR SpelNodeImpl rhExpr = eatLogicalAndExpression(); checkOperands(t, expr, rhExpr); expr = new OpOr(t.startPos, t.endPos, expr, rhExpr); } return expr; }
private boolean maybeEatParenExpression() { if (peekToken(TokenKind.LPAREN)) { nextToken(); SpelNodeImpl expr = eatExpression(); Assert.state(expr != null, "No node"); eatToken(TokenKind.RPAREN); push(expr); return true; } else { return false; } }
@Nullable private SpelNodeImpl eatNode() { return (peekToken(TokenKind.DOT, TokenKind.SAFE_NAVI) ? eatDottedNode() : eatNonDottedNode()); }
private boolean maybeEatConstructorReference() { if (peekIdentifierToken("new")) { Token newToken = takeToken(); if (peekToken(TokenKind.RSQUARE)) { push(new PropertyOrFieldReference(false, newToken.stringValue(), newToken.startPos, newToken.endPos)); return true; SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId(); List<SpelNodeImpl> nodes = new ArrayList<>(); nodes.add(possiblyQualifiedConstructorName); if (peekToken(TokenKind.LSQUARE)) { while (peekToken(TokenKind.LSQUARE, true)) { if (!peekToken(TokenKind.RSQUARE)) { dimensions.add(eatExpression()); eatToken(TokenKind.RSQUARE); if (maybeEatInlineListOrMap()) { nodes.add(pop()); push(new ConstructorReference(newToken.startPos, newToken.endPos, dimensions.toArray(new SpelNodeImpl[0]), nodes.toArray(new SpelNodeImpl[0]))); eatConstructorArgs(nodes); push(new ConstructorReference(newToken.startPos, newToken.endPos, nodes.toArray(new SpelNodeImpl[0])));
private boolean maybeEatProjection(boolean nullSafeNavigation) { Token t = peekToken(); if (!peekToken(TokenKind.PROJECT, true)) { return false; } Assert.state(t != null, "No token"); SpelNodeImpl expr = eatExpression(); Assert.state(expr != null, "No node"); eatToken(TokenKind.RSQUARE); this.constructedNodes.push(new Projection(nullSafeNavigation, toPos(t), expr)); return true; }
private boolean maybeEatSelection(boolean nullSafeNavigation) { Token t = peekToken(); if (!peekSelectToken()) { return false; } Assert.state(t != null, "No token"); nextToken(); SpelNodeImpl expr = eatExpression(); if (expr == null) { throw internalException(t.startPos, SpelMessage.MISSING_SELECTION_EXPRESSION); } eatToken(TokenKind.RSQUARE); if (t.kind == TokenKind.SELECT_FIRST) { this.constructedNodes.push(new Selection(nullSafeNavigation, Selection.FIRST, t.startPos, t.endPos, expr)); } else if (t.kind == TokenKind.SELECT_LAST) { this.constructedNodes.push(new Selection(nullSafeNavigation, Selection.LAST, t.startPos, t.endPos, expr)); } else { this.constructedNodes.push(new Selection(nullSafeNavigation, Selection.ALL, t.startPos, t.endPos, expr)); } return true; }
@Nullable private SpelNodeImpl eatLogicalAndExpression() { SpelNodeImpl expr = eatRelationalExpression(); while (peekIdentifierToken("and") || peekToken(TokenKind.SYMBOLIC_AND)) { Token t = takeToken(); // consume 'AND' SpelNodeImpl rhExpr = eatRelationalExpression(); checkOperands(t, expr, rhExpr); expr = new OpAnd(t.startPos, t.endPos, expr, rhExpr); } return expr; }
@Nullable private SpelNodeImpl eatExpression() { SpelNodeImpl expr = eatLogicalOrExpression(); Token t = peekToken(); if (t != null) { if (t.kind == TokenKind.ASSIGN) { // a=b expr = new NullLiteral(t.startPos - 1, t.endPos - 1); nextToken(); SpelNodeImpl assignedValue = eatLogicalOrExpression(); return new Assign(t.startPos, t.endPos, expr, assignedValue); expr = new NullLiteral(t.startPos - 1, t.endPos - 2); nextToken(); // elvis has left the building SpelNodeImpl valueIfNull = eatExpression(); if (valueIfNull == null) { valueIfNull = new NullLiteral(t.startPos + 1, t.endPos + 1); expr = new NullLiteral(t.startPos - 1, t.endPos - 1); nextToken(); SpelNodeImpl ifTrueExprValue = eatExpression(); eatToken(TokenKind.COLON); SpelNodeImpl ifFalseExprValue = eatExpression(); return new Ternary(t.startPos, t.endPos, expr, ifTrueExprValue, ifFalseExprValue);
@Nullable private SpelNodeImpl eatSumExpression() { SpelNodeImpl expr = eatProductExpression(); while (peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.INC)) { Token t = takeToken(); //consume PLUS or MINUS or INC SpelNodeImpl rhExpr = eatProductExpression(); checkRightOperand(t, rhExpr); if (t.kind == TokenKind.PLUS) { expr = new OpPlus(t.startPos, t.endPos, expr, rhExpr); } else if (t.kind == TokenKind.MINUS) { expr = new OpMinus(t.startPos, t.endPos, expr, rhExpr); } } return expr; }
@Nullable private SpelNodeImpl eatPowerIncDecExpression() { SpelNodeImpl expr = eatUnaryExpression(); if (peekToken(TokenKind.POWER)) { Token t = takeToken(); //consume POWER SpelNodeImpl rhExpr = eatUnaryExpression(); checkRightOperand(t, rhExpr); return new OperatorPower(t.startPos, t.endPos, expr, rhExpr); } if (expr != null && peekToken(TokenKind.INC, TokenKind.DEC)) { Token t = takeToken(); //consume INC/DEC if (t.getKind() == TokenKind.INC) { return new OpInc(t.startPos, t.endPos, true, expr); } return new OpDec(t.startPos, t.endPos, true, expr); } return expr; }
@Nullable private SpelNodeImpl eatProductExpression() { SpelNodeImpl expr = eatPowerIncDecExpression(); while (peekToken(TokenKind.STAR, TokenKind.DIV, TokenKind.MOD)) { Token t = takeToken(); // consume STAR/DIV/MOD SpelNodeImpl rhExpr = eatPowerIncDecExpression(); checkOperands(t, expr, rhExpr); if (t.kind == TokenKind.STAR) { expr = new OpMultiply(t.startPos, t.endPos, expr, rhExpr); } else if (t.kind == TokenKind.DIV) { expr = new OpDivide(t.startPos, t.endPos, expr, rhExpr); } else { Assert.isTrue(t.kind == TokenKind.MOD, "Mod token expected"); expr = new OpModulus(t.startPos, t.endPos, expr, rhExpr); } } return expr; }
@Nullable private SpelNodeImpl eatRelationalExpression() { SpelNodeImpl expr = eatSumExpression(); Token relationalOperatorToken = maybeEatRelationalOperator(); if (relationalOperatorToken != null) { Token t = takeToken(); // consume relational operator token SpelNodeImpl rhExpr = eatSumExpression(); checkOperands(t, expr, rhExpr); TokenKind tk = relationalOperatorToken.kind;
private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) { if (!peekToken(TokenKind.LPAREN)) { throw new InternalParseException(new SpelParseException(this.expressionString, positionOf(peekToken()), SpelMessage.MISSING_CONSTRUCTOR_ARGS)); } consumeArguments(accumulatedArguments); eatToken(TokenKind.RPAREN); }
@Override protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException { try { this.expressionString = expressionString; Tokenizer tokenizer = new Tokenizer(expressionString); this.tokenStream = tokenizer.process(); this.tokenStreamLength = this.tokenStream.size(); this.tokenStreamPointer = 0; this.constructedNodes.clear(); SpelNodeImpl ast = eatExpression(); Assert.state(ast != null, "No node"); Token t = peekToken(); if (t != null) { throw new SpelParseException(t.startPos, SpelMessage.MORE_INPUT, toString(nextToken())); } Assert.isTrue(this.constructedNodes.isEmpty(), "At least one node expected"); return new SpelExpression(expressionString, ast, this.configuration); } catch (InternalParseException ex) { throw ex.getCause(); } }
/** * Used for consuming arguments for either a method or a constructor call. */ private void consumeArguments(List<SpelNodeImpl> accumulatedArguments) { Token t = peekToken(); Assert.state(t != null, "Expected token"); int pos = t.startPos; Token next; do { nextToken(); // consume (first time through) or comma (subsequent times) t = peekToken(); if (t == null) { throw internalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } if (t.kind != TokenKind.RPAREN) { accumulatedArguments.add(eatExpression()); } next = peekToken(); } while (next != null && next.kind == TokenKind.COMMA); if (next == null) { throw internalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } }
@Nullable private SpelNodeImpl[] maybeEatMethodArgs() { if (!peekToken(TokenKind.LPAREN)) { return null; } List<SpelNodeImpl> args = new ArrayList<>(); consumeArguments(args); eatToken(TokenKind.RPAREN); return args.toArray(new SpelNodeImpl[0]); }
private boolean maybeEatIndexer() { Token t = peekToken(); if (!peekToken(TokenKind.LSQUARE, true)) { return false; } Assert.state(t != null, "No token"); SpelNodeImpl expr = eatExpression(); Assert.state(expr != null, "No node"); eatToken(TokenKind.RSQUARE); this.constructedNodes.push(new Indexer(t.startPos, t.endPos, expr)); return true; }
private boolean maybeEatConstructorReference() { if (peekIdentifierToken("new")) { Token newToken = takeToken(); if (peekToken(TokenKind.RSQUARE)) { push(new PropertyOrFieldReference(false, newToken.stringValue(), toPos(newToken))); return true; SpelNodeImpl possiblyQualifiedConstructorName = eatPossiblyQualifiedId(); List<SpelNodeImpl> nodes = new ArrayList<>(); nodes.add(possiblyQualifiedConstructorName); if (peekToken(TokenKind.LSQUARE)) { while (peekToken(TokenKind.LSQUARE, true)) { if (!peekToken(TokenKind.RSQUARE)) { dimensions.add(eatExpression()); eatToken(TokenKind.RSQUARE); if (maybeEatInlineListOrMap()) { nodes.add(pop()); push(new ConstructorReference(toPos(newToken), dimensions.toArray(new SpelNodeImpl[0]), nodes.toArray(new SpelNodeImpl[0]))); eatConstructorArgs(nodes); push(new ConstructorReference(toPos(newToken), nodes.toArray(new SpelNodeImpl[0])));