1 源码解析
1.1 源码解析1(jdk中的应用)
1.2 源码解析2(Spring中的应用)
1.3 源码解析为何算出666?
1 源码解析
1.1 源码解析1(jdk中的应用)
java.util.regex.Pattern
(java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现)
1.2 源码解析2(Spring中的应用)
测试类:(通过el表达式计算出结果)(以下代码中红色粗体为跳转顺序)
package com.geely.design.pattern.behavioral.interpreter; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; /** * Created by geely */ public class SpringTest { public static void main(String[] args) { org.springframework.expression.ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66"); int result = (Integer) expression.getValue(); System.out.println(result); } }
应用类1:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.expression.common; import java.util.LinkedList; import java.util.List; import java.util.Stack; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParseException; import org.springframework.expression.ParserContext; public abstract class TemplateAwareExpressionParser implements ExpressionParser { private static final ParserContext NON_TEMPLATE_PARSER_CONTEXT = new ParserContext() { public String getExpressionPrefix() { return null; } public String getExpressionSuffix() { return null; } public boolean isTemplate() { return false; } }; public TemplateAwareExpressionParser() { } public Expression parseExpression(String expressionString) throws ParseException { return this.parseExpression(expressionString, NON_TEMPLATE_PARSER_CONTEXT); } public Expression parseExpression(String expressionString, ParserContext context) throws ParseException { if (context == null) { context = NON_TEMPLATE_PARSER_CONTEXT; } return context.isTemplate() ? this.parseTemplate(expressionString, context) : this.doParseExpression(expressionString, context); } private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException { if (expressionString.length() == 0) { return new LiteralExpression(""); } else { Expression[] expressions = this.parseExpressions(expressionString, context); return (Expression)(expressions.length == 1 ? expressions[0] : new CompositeStringExpression(expressionString, expressions)); } } private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParseException { List<Expression> expressions = new LinkedList(); String prefix = context.getExpressionPrefix(); String suffix = context.getExpressionSuffix(); int startIdx = 0; while(startIdx < expressionString.length()) { int prefixIndex = expressionString.indexOf(prefix, startIdx); if (prefixIndex >= startIdx) { if (prefixIndex > startIdx) { expressions.add(this.createLiteralExpression(context, expressionString.substring(startIdx, prefixIndex))); } int afterPrefixIndex = prefixIndex + prefix.length(); int suffixIndex = this.skipToCorrectEndSuffix(prefix, suffix, expressionString, afterPrefixIndex); if (suffixIndex == -1) { throw new ParseException(expressionString, prefixIndex, "No ending suffix '" + suffix + "' for expression starting at character " + prefixIndex + ": " + expressionString.substring(prefixIndex)); } if (suffixIndex == afterPrefixIndex) { throw new ParseException(expressionString, prefixIndex, "No expression defined within delimiter '" + prefix + suffix + "' at character " + prefixIndex); } String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex); expr = expr.trim(); if (expr.length() == 0) { throw new ParseException(expressionString, prefixIndex, "No expression defined within delimiter '" + prefix + suffix + "' at character " + prefixIndex); } expressions.add(this.doParseExpression(expr, context)); startIdx = suffixIndex + suffix.length(); } else { expressions.add(this.createLiteralExpression(context, expressionString.substring(startIdx))); startIdx = expressionString.length(); } } return (Expression[])expressions.toArray(new Expression[expressions.size()]); } private Expression createLiteralExpression(ParserContext context, String text) { return new LiteralExpression(text); } private boolean isSuffixHere(String expressionString, int pos, String suffix) { int suffixPosition = 0; for(int i = 0; i < suffix.length() && pos < expressionString.length(); ++i) { if (expressionString.charAt(pos++) != suffix.charAt(suffixPosition++)) { return false; } } return suffixPosition == suffix.length(); } private int skipToCorrectEndSuffix(String prefix, String suffix, String expressionString, int afterPrefixIndex) throws ParseException { int pos = afterPrefixIndex; int maxlen = expressionString.length(); int nextSuffix = expressionString.indexOf(suffix, afterPrefixIndex); if (nextSuffix == -1) { return -1; } else { Stack stack; for(stack = new Stack(); pos < maxlen && (!this.isSuffixHere(expressionString, pos, suffix) || !stack.isEmpty()); ++pos) { char ch = expressionString.charAt(pos); switch(ch) { case '"': case '\'': int endLiteral = expressionString.indexOf(ch, pos + 1); if (endLiteral == -1) { throw new ParseException(expressionString, pos, "Found non terminating string literal starting at position " + pos); } pos = endLiteral; break; case '(': case '[': case '{': stack.push(new TemplateAwareExpressionParser.Bracket(ch, pos)); break; case ')': case ']': case '}': if (stack.isEmpty()) { throw new ParseException(expressionString, pos, "Found closing '" + ch + "' at position " + pos + " without an opening '" + TemplateAwareExpressionParser.Bracket.theOpenBracketFor(ch) + "'"); } TemplateAwareExpressionParser.Bracket p = (TemplateAwareExpressionParser.Bracket)stack.pop(); if (!p.compatibleWithCloseBracket(ch)) { throw new ParseException(expressionString, pos, "Found closing '" + ch + "' at position " + pos + " but most recent opening is '" + p.bracket + "' at position " + p.pos); } } } if (!stack.isEmpty()) { TemplateAwareExpressionParser.Bracket p = (TemplateAwareExpressionParser.Bracket)stack.pop(); throw new ParseException(expressionString, p.pos, "Missing closing '" + TemplateAwareExpressionParser.Bracket.theCloseBracketFor(p.bracket) + "' for '" + p.bracket + "' at position " + p.pos); } else { return !this.isSuffixHere(expressionString, pos, suffix) ? -1 : pos; } } } protected abstract Expression doParseExpression(String var1, ParserContext var2) throws ParseException; private static class Bracket { char bracket; int pos; Bracket(char bracket, int pos) { this.bracket = bracket; this.pos = pos; } boolean compatibleWithCloseBracket(char closeBracket) { if (this.bracket == '{') { return closeBracket == '}'; } else if (this.bracket == '[') { return closeBracket == ']'; } else { return closeBracket == ')'; } } static char theOpenBracketFor(char closeBracket) { if (closeBracket == '}') { return '{'; } else { return (char)(closeBracket == ']' ? '[' : '('); } } static char theCloseBracketFor(char openBracket) { if (openBracket == '{') { return '}'; } else { return (char)(openBracket == '[' ? ']' : ')'); } } } }
应用类2(继承了应用类1):
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.expression.spel.standard; import org.springframework.expression.ParseException; import org.springframework.expression.ParserContext; import org.springframework.expression.common.TemplateAwareExpressionParser; import org.springframework.expression.spel.SpelParserConfiguration; import org.springframework.util.Assert; public class SpelExpressionParser extends TemplateAwareExpressionParser { private final SpelParserConfiguration configuration; public SpelExpressionParser() { this.configuration = new SpelParserConfiguration(false, false); } public SpelExpressionParser(SpelParserConfiguration configuration) { Assert.notNull(configuration, "SpelParserConfiguration must not be null"); this.configuration = configuration; } protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException { return (new InternalSpelExpressionParser(this.configuration)).doParseExpression(expressionString, context); } public SpelExpression parseRaw(String expressionString) throws ParseException { return this.doParseExpression(expressionString, (ParserContext)null); } }
应用类3(继承了应用类1):
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.expression.spel.standard; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Stack; import java.util.regex.Pattern; import org.springframework.expression.ParseException; import org.springframework.expression.ParserContext; import org.springframework.expression.common.TemplateAwareExpressionParser; import org.springframework.expression.spel.InternalParseException; import org.springframework.expression.spel.SpelMessage; import org.springframework.expression.spel.SpelParseException; import org.springframework.expression.spel.SpelParserConfiguration; import org.springframework.expression.spel.ast.Assign; import org.springframework.expression.spel.ast.BeanReference; import org.springframework.expression.spel.ast.BooleanLiteral; import org.springframework.expression.spel.ast.CompoundExpression; import org.springframework.expression.spel.ast.ConstructorReference; import org.springframework.expression.spel.ast.Elvis; import org.springframework.expression.spel.ast.FunctionReference; import org.springframework.expression.spel.ast.Identifier; import org.springframework.expression.spel.ast.Indexer; import org.springframework.expression.spel.ast.InlineList; import org.springframework.expression.spel.ast.Literal; import org.springframework.expression.spel.ast.MethodReference; import org.springframework.expression.spel.ast.NullLiteral; import org.springframework.expression.spel.ast.OpAnd; import org.springframework.expression.spel.ast.OpDec; import org.springframework.expression.spel.ast.OpDivide; import org.springframework.expression.spel.ast.OpEQ; import org.springframework.expression.spel.ast.OpGE; import org.springframework.expression.spel.ast.OpGT; import org.springframework.expression.spel.ast.OpInc; import org.springframework.expression.spel.ast.OpLE; import org.springframework.expression.spel.ast.OpLT; import org.springframework.expression.spel.ast.OpMinus; import org.springframework.expression.spel.ast.OpModulus; import org.springframework.expression.spel.ast.OpMultiply; import org.springframework.expression.spel.ast.OpNE; import org.springframework.expression.spel.ast.OpOr; import org.springframework.expression.spel.ast.OpPlus; import org.springframework.expression.spel.ast.OperatorBetween; import org.springframework.expression.spel.ast.OperatorInstanceof; import org.springframework.expression.spel.ast.OperatorMatches; import org.springframework.expression.spel.ast.OperatorNot; import org.springframework.expression.spel.ast.OperatorPower; import org.springframework.expression.spel.ast.Projection; import org.springframework.expression.spel.ast.PropertyOrFieldReference; import org.springframework.expression.spel.ast.QualifiedIdentifier; import org.springframework.expression.spel.ast.Selection; import org.springframework.expression.spel.ast.SpelNodeImpl; import org.springframework.expression.spel.ast.StringLiteral; import org.springframework.expression.spel.ast.Ternary; import org.springframework.expression.spel.ast.TypeReference; import org.springframework.expression.spel.ast.VariableReference; import org.springframework.util.Assert; import org.springframework.util.StringUtils; class InternalSpelExpressionParser extends TemplateAwareExpressionParser { private static final Pattern VALID_QUALIFIED_ID_PATTERN = Pattern.compile("[\\p{L}\\p{N}_$]+"); private String expressionString; private List<Token> tokenStream; private int tokenStreamLength; private int tokenStreamPointer; private final Stack<SpelNodeImpl> constructedNodes = new Stack(); private final SpelParserConfiguration configuration; public InternalSpelExpressionParser(SpelParserConfiguration configuration) { this.configuration = configuration; } protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException { try { this.expressionString = expressionString; Tokenizer tokenizer = new Tokenizer(expressionString); tokenizer.process(); this.tokenStream = tokenizer.getTokens(); this.tokenStreamLength = this.tokenStream.size(); this.tokenStreamPointer = 0; this.constructedNodes.clear(); SpelNodeImpl ast = this.eatExpression(); if (this.moreTokens()) { throw new SpelParseException(this.peekToken().startpos, SpelMessage.MORE_INPUT, new Object[]{this.toString(this.nextToken())}); } else { Assert.isTrue(this.constructedNodes.isEmpty()); return new SpelExpression(expressionString, ast, this.configuration); } } catch (InternalParseException var5) { throw var5.getCause(); } } private SpelNodeImpl eatExpression() { SpelNodeImpl expr = this.eatLogicalOrExpression(); if (this.moreTokens()) { Token t = this.peekToken(); SpelNodeImpl ifTrueExprValue; if (t.kind == TokenKind.ASSIGN) { if (expr == null) { expr = new NullLiteral(this.toPos(t.startpos - 1, t.endpos - 1)); } this.nextToken(); ifTrueExprValue = this.eatLogicalOrExpression(); return new Assign(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, ifTrueExprValue}); } if (t.kind == TokenKind.ELVIS) { if (expr == null) { expr = new NullLiteral(this.toPos(t.startpos - 1, t.endpos - 2)); } this.nextToken(); SpelNodeImpl valueIfNull = this.eatExpression(); if (valueIfNull == null) { valueIfNull = new NullLiteral(this.toPos(t.startpos + 1, t.endpos + 1)); } return new Elvis(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, (SpelNodeImpl)valueIfNull}); } if (t.kind == TokenKind.QMARK) { if (expr == null) { expr = new NullLiteral(this.toPos(t.startpos - 1, t.endpos - 1)); } this.nextToken(); ifTrueExprValue = this.eatExpression(); this.eatToken(TokenKind.COLON); SpelNodeImpl ifFalseExprValue = this.eatExpression(); return new Ternary(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, ifTrueExprValue, ifFalseExprValue}); } } return (SpelNodeImpl)expr; } private SpelNodeImpl eatLogicalOrExpression() { Object expr; Token t; SpelNodeImpl rhExpr; for(expr = this.eatLogicalAndExpression(); this.peekIdentifierToken("or") || this.peekToken(TokenKind.SYMBOLIC_OR); expr = new OpOr(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr})) { t = this.nextToken(); rhExpr = this.eatLogicalAndExpression(); this.checkOperands(t, (SpelNodeImpl)expr, rhExpr); } return (SpelNodeImpl)expr; } private SpelNodeImpl eatLogicalAndExpression() { Object expr; Token t; SpelNodeImpl rhExpr; for(expr = this.eatRelationalExpression(); this.peekIdentifierToken("and") || this.peekToken(TokenKind.SYMBOLIC_AND); expr = new OpAnd(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr})) { t = this.nextToken(); rhExpr = this.eatRelationalExpression(); this.checkOperands(t, (SpelNodeImpl)expr, rhExpr); } return (SpelNodeImpl)expr; } private SpelNodeImpl eatRelationalExpression() { SpelNodeImpl expr = this.eatSumExpression(); Token relationalOperatorToken = this.maybeEatRelationalOperator(); if (relationalOperatorToken != null) { Token t = this.nextToken(); SpelNodeImpl rhExpr = this.eatSumExpression(); this.checkOperands(t, expr, rhExpr); TokenKind tk = relationalOperatorToken.kind; if (relationalOperatorToken.isNumericRelationalOperator()) { int pos = this.toPos(t); if (tk == TokenKind.GT) { return new OpGT(pos, new SpelNodeImpl[]{expr, rhExpr}); } else if (tk == TokenKind.LT) { return new OpLT(pos, new SpelNodeImpl[]{expr, rhExpr}); } else if (tk == TokenKind.LE) { return new OpLE(pos, new SpelNodeImpl[]{expr, rhExpr}); } else if (tk == TokenKind.GE) { return new OpGE(pos, new SpelNodeImpl[]{expr, rhExpr}); } else if (tk == TokenKind.EQ) { return new OpEQ(pos, new SpelNodeImpl[]{expr, rhExpr}); } else { Assert.isTrue(tk == TokenKind.NE); return new OpNE(pos, new SpelNodeImpl[]{expr, rhExpr}); } } else if (tk == TokenKind.INSTANCEOF) { return new OperatorInstanceof(this.toPos(t), new SpelNodeImpl[]{expr, rhExpr}); } else if (tk == TokenKind.MATCHES) { return new OperatorMatches(this.toPos(t), new SpelNodeImpl[]{expr, rhExpr}); } else { Assert.isTrue(tk == TokenKind.BETWEEN); return new OperatorBetween(this.toPos(t), new SpelNodeImpl[]{expr, rhExpr}); } } else { return expr; } } private SpelNodeImpl eatSumExpression() { Object expr = this.eatProductExpression(); while(this.peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.INC)) { Token t = this.nextToken(); SpelNodeImpl rhExpr = this.eatProductExpression(); this.checkRightOperand(t, rhExpr); if (t.kind == TokenKind.PLUS) { expr = new OpPlus(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr}); } else if (t.kind == TokenKind.MINUS) { expr = new OpMinus(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr}); } } return (SpelNodeImpl)expr; } private SpelNodeImpl eatProductExpression() { Object expr = this.eatPowerIncDecExpression(); while(this.peekToken(TokenKind.STAR, TokenKind.DIV, TokenKind.MOD)) { Token t = this.nextToken(); SpelNodeImpl rhExpr = this.eatPowerIncDecExpression(); this.checkOperands(t, (SpelNodeImpl)expr, rhExpr); if (t.kind == TokenKind.STAR) { expr = new OpMultiply(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr}); } else if (t.kind == TokenKind.DIV) { expr = new OpDivide(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr}); } else { Assert.isTrue(t.kind == TokenKind.MOD); expr = new OpModulus(this.toPos(t), new SpelNodeImpl[]{(SpelNodeImpl)expr, rhExpr}); } } return (SpelNodeImpl)expr; } private SpelNodeImpl eatPowerIncDecExpression() { SpelNodeImpl expr = this.eatUnaryExpression(); Token t; if (this.peekToken(TokenKind.POWER)) { t = this.nextToken(); SpelNodeImpl rhExpr = this.eatUnaryExpression(); this.checkRightOperand(t, rhExpr); return new OperatorPower(this.toPos(t), new SpelNodeImpl[]{expr, rhExpr}); } else if (expr != null && this.peekToken(TokenKind.INC, TokenKind.DEC)) { t = this.nextToken(); return (SpelNodeImpl)(t.getKind() == TokenKind.INC ? new OpInc(this.toPos(t), true, new SpelNodeImpl[]{expr}) : new OpDec(this.toPos(t), true, new SpelNodeImpl[]{expr})); } else { return expr; } } private SpelNodeImpl eatUnaryExpression() { Token t; SpelNodeImpl expr; if (this.peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.NOT)) { t = this.nextToken(); expr = this.eatUnaryExpression(); if (t.kind == TokenKind.NOT) { return new OperatorNot(this.toPos(t), expr); } else if (t.kind == TokenKind.PLUS) { return new OpPlus(this.toPos(t), new SpelNodeImpl[]{expr}); } else { Assert.isTrue(t.kind == TokenKind.MINUS); return new OpMinus(this.toPos(t), new SpelNodeImpl[]{expr}); } } else if (this.peekToken(TokenKind.INC, TokenKind.DEC)) { t = this.nextToken(); expr = this.eatUnaryExpression(); return (SpelNodeImpl)(t.getKind() == TokenKind.INC ? new OpInc(this.toPos(t), false, new SpelNodeImpl[]{expr}) : new OpDec(this.toPos(t), false, new SpelNodeImpl[]{expr})); } else { return this.eatPrimaryExpression(); } } private SpelNodeImpl eatPrimaryExpression() { List<SpelNodeImpl> nodes = new ArrayList(); SpelNodeImpl start = this.eatStartNode(); nodes.add(start); while(this.maybeEatNode()) { nodes.add(this.pop()); } return (SpelNodeImpl)(nodes.size() == 1 ? (SpelNodeImpl)nodes.get(0) : new CompoundExpression(this.toPos(start.getStartPosition(), ((SpelNodeImpl)nodes.get(nodes.size() - 1)).getEndPosition()), (SpelNodeImpl[])nodes.toArray(new SpelNodeImpl[nodes.size()]))); } private boolean maybeEatNode() { SpelNodeImpl expr = null; if (this.peekToken(TokenKind.DOT, TokenKind.SAFE_NAVI)) { expr = this.eatDottedNode(); } else { expr = this.maybeEatNonDottedNode(); } if (expr == null) { return false; } else { this.push(expr); return true; } } private SpelNodeImpl maybeEatNonDottedNode() { return this.peekToken(TokenKind.LSQUARE) && this.maybeEatIndexer() ? this.pop() : null; } private SpelNodeImpl eatDottedNode() { Token t = this.nextToken(); boolean nullSafeNavigation = t.kind == TokenKind.SAFE_NAVI; if (!this.maybeEatMethodOrProperty(nullSafeNavigation) && !this.maybeEatFunctionOrVar() && !this.maybeEatProjection(nullSafeNavigation) && !this.maybeEatSelection(nullSafeNavigation)) { if (this.peekToken() == null) { this.raiseInternalException(t.startpos, SpelMessage.OOD); } else { this.raiseInternalException(t.startpos, SpelMessage.UNEXPECTED_DATA_AFTER_DOT, this.toString(this.peekToken())); } return null; } else { return this.pop(); } } private boolean maybeEatFunctionOrVar() { if (!this.peekToken(TokenKind.HASH)) { return false; } else { Token t = this.nextToken(); Token functionOrVariableName = this.eatToken(TokenKind.IDENTIFIER); SpelNodeImpl[] args = this.maybeEatMethodArgs(); if (args == null) { this.push(new VariableReference(functionOrVariableName.data, this.toPos(t.startpos, functionOrVariableName.endpos))); return true; } else { this.push(new FunctionReference(functionOrVariableName.data, this.toPos(t.startpos, functionOrVariableName.endpos), args)); return true; } } } private SpelNodeImpl[] maybeEatMethodArgs() { if (!this.peekToken(TokenKind.LPAREN)) { return null; } else { List<SpelNodeImpl> args = new ArrayList(); this.consumeArguments(args); this.eatToken(TokenKind.RPAREN); return (SpelNodeImpl[])args.toArray(new SpelNodeImpl[args.size()]); } } private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) { if (!this.peekToken(TokenKind.LPAREN)) { throw new InternalParseException(new SpelParseException(this.expressionString, this.positionOf(this.peekToken()), SpelMessage.MISSING_CONSTRUCTOR_ARGS, new Object[0])); } else { this.consumeArguments(accumulatedArguments); this.eatToken(TokenKind.RPAREN); } } private void consumeArguments(List<SpelNodeImpl> accumulatedArguments) { int pos = this.peekToken().startpos; Token next = null; do { this.nextToken(); Token t = this.peekToken(); if (t == null) { this.raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } if (t.kind != TokenKind.RPAREN) { accumulatedArguments.add(this.eatExpression()); } next = this.peekToken(); } while(next != null && next.kind == TokenKind.COMMA); if (next == null) { this.raiseInternalException(pos, SpelMessage.RUN_OUT_OF_ARGUMENTS); } } private int positionOf(Token t) { return t == null ? this.expressionString.length() : t.startpos; } private SpelNodeImpl eatStartNode() { if (this.maybeEatLiteral()) { return this.pop(); } else if (this.maybeEatParenExpression()) { return this.pop(); } else if (!this.maybeEatTypeReference() && !this.maybeEatNullReference() && !this.maybeEatConstructorReference() && !this.maybeEatMethodOrProperty(false) && !this.maybeEatFunctionOrVar()) { if (this.maybeEatBeanReference()) { return this.pop(); } else if (!this.maybeEatProjection(false) && !this.maybeEatSelection(false) && !this.maybeEatIndexer()) { return this.maybeEatInlineList() ? this.pop() : null; } else { return this.pop(); } } else { return this.pop(); } } private boolean maybeEatBeanReference() { if (this.peekToken(TokenKind.BEAN_REF)) { Token beanRefToken = this.nextToken(); Token beanNameToken = null; String beanname = null; if (this.peekToken(TokenKind.IDENTIFIER)) { beanNameToken = this.eatToken(TokenKind.IDENTIFIER); beanname = beanNameToken.data; } else if (this.peekToken(TokenKind.LITERAL_STRING)) { beanNameToken = this.eatToken(TokenKind.LITERAL_STRING); beanname = beanNameToken.stringValue(); beanname = beanname.substring(1, beanname.length() - 1); } else { this.raiseInternalException(beanRefToken.startpos, SpelMessage.INVALID_BEAN_REFERENCE); } BeanReference beanReference = new BeanReference(this.toPos(beanNameToken), beanname); this.constructedNodes.push(beanReference); return true; } else { return false; } } private boolean maybeEatTypeReference() { if (!this.peekToken(TokenKind.IDENTIFIER)) { return false; } else { Token typeName = this.peekToken(); if (!typeName.stringValue().equals("T")) { return false; } else { this.nextToken(); this.eatToken(TokenKind.LPAREN); SpelNodeImpl node = this.eatPossiblyQualifiedId(); int dims; for(dims = 0; this.peekToken(TokenKind.LSQUARE, true); ++dims) { this.eatToken(TokenKind.RSQUARE); } this.eatToken(TokenKind.RPAREN); this.constructedNodes.push(new TypeReference(this.toPos(typeName), node, dims)); return true; } } } private boolean maybeEatNullReference() { if (this.peekToken(TokenKind.IDENTIFIER)) { Token nullToken = this.peekToken(); if (!nullToken.stringValue().equalsIgnoreCase("null")) { return false; } else { this.nextToken(); this.constructedNodes.push(new NullLiteral(this.toPos(nullToken))); return true; } } else { return false; } } private boolean maybeEatProjection(boolean nullSafeNavigation) { Token t = this.peekToken(); if (!this.peekToken(TokenKind.PROJECT, true)) { return false; } else { SpelNodeImpl expr = this.eatExpression(); this.eatToken(TokenKind.RSQUARE); this.constructedNodes.push(new Projection(nullSafeNavigation, this.toPos(t), expr)); return true; } } private boolean maybeEatInlineList() { Token t = this.peekToken(); if (!this.peekToken(TokenKind.LCURLY, true)) { return false; } else { SpelNodeImpl expr = null; Token closingCurly = this.peekToken(); if (this.peekToken(TokenKind.RCURLY, true)) { expr = new InlineList(this.toPos(t.startpos, closingCurly.endpos), new SpelNodeImpl[0]); } else { ArrayList listElements = new ArrayList(); do { listElements.add(this.eatExpression()); } while(this.peekToken(TokenKind.COMMA, true)); closingCurly = this.eatToken(TokenKind.RCURLY); expr = new InlineList(this.toPos(t.startpos, closingCurly.endpos), (SpelNodeImpl[])listElements.toArray(new SpelNodeImpl[listElements.size()])); } this.constructedNodes.push(expr); return true; } } private boolean maybeEatIndexer() { Token t = this.peekToken(); if (!this.peekToken(TokenKind.LSQUARE, true)) { return false; } else { SpelNodeImpl expr = this.eatExpression(); this.eatToken(TokenKind.RSQUARE); this.constructedNodes.push(new Indexer(this.toPos(t), expr)); return true; } } private boolean maybeEatSelection(boolean nullSafeNavigation) { Token t = this.peekToken(); if (!this.peekSelectToken()) { return false; } else { this.nextToken(); SpelNodeImpl expr = this.eatExpression(); if (expr == null) { this.raiseInternalException(this.toPos(t), SpelMessage.MISSING_SELECTION_EXPRESSION); } this.eatToken(TokenKind.RSQUARE); if (t.kind == TokenKind.SELECT_FIRST) { this.constructedNodes.push(new Selection(nullSafeNavigation, 1, this.toPos(t), expr)); } else if (t.kind == TokenKind.SELECT_LAST) { this.constructedNodes.push(new Selection(nullSafeNavigation, 2, this.toPos(t), expr)); } else { this.constructedNodes.push(new Selection(nullSafeNavigation, 0, this.toPos(t), expr)); } return true; } } private SpelNodeImpl eatPossiblyQualifiedId() { LinkedList<SpelNodeImpl> qualifiedIdPieces = new LinkedList(); Token node; for(node = this.peekToken(); this.isValidQualifiedId(node); node = this.peekToken()) { this.nextToken(); if (node.kind != TokenKind.DOT) { qualifiedIdPieces.add(new Identifier(node.stringValue(), this.toPos(node))); } } if (qualifiedIdPieces.isEmpty()) { if (node == null) { this.raiseInternalException(this.expressionString.length(), SpelMessage.OOD); } this.raiseInternalException(node.startpos, SpelMessage.NOT_EXPECTED_TOKEN, "qualified ID", node.getKind().toString().toLowerCase()); } int pos = this.toPos(((SpelNodeImpl)qualifiedIdPieces.getFirst()).getStartPosition(), ((SpelNodeImpl)qualifiedIdPieces.getLast()).getEndPosition()); return new QualifiedIdentifier(pos, (SpelNodeImpl[])qualifiedIdPieces.toArray(new SpelNodeImpl[qualifiedIdPieces.size()])); } private boolean isValidQualifiedId(Token node) { if (node != null && node.kind != TokenKind.LITERAL_STRING) { if (node.kind != TokenKind.DOT && node.kind != TokenKind.IDENTIFIER) { String value = node.stringValue(); return StringUtils.hasLength(value) && VALID_QUALIFIED_ID_PATTERN.matcher(value).matches(); } else { return true; } } else { return false; } } private boolean maybeEatMethodOrProperty(boolean nullSafeNavigation) { if (this.peekToken(TokenKind.IDENTIFIER)) { Token methodOrPropertyName = this.nextToken(); SpelNodeImpl[] args = this.maybeEatMethodArgs(); if (args == null) { this.push(new PropertyOrFieldReference(nullSafeNavigation, methodOrPropertyName.data, this.toPos(methodOrPropertyName))); return true; } else { this.push(new MethodReference(nullSafeNavigation, methodOrPropertyName.data, this.toPos(methodOrPropertyName), args)); return true; } } else { return false; } } private boolean maybeEatConstructorReference() { if (!this.peekIdentifierToken("new")) { return false; } else { Token newToken = this.nextToken(); SpelNodeImpl possiblyQualifiedConstructorName = this.eatPossiblyQualifiedId(); List<SpelNodeImpl> nodes = new ArrayList(); nodes.add(possiblyQualifiedConstructorName); if (this.peekToken(TokenKind.LSQUARE)) { ArrayList dimensions; for(dimensions = new ArrayList(); this.peekToken(TokenKind.LSQUARE, true); this.eatToken(TokenKind.RSQUARE)) { if (!this.peekToken(TokenKind.RSQUARE)) { dimensions.add(this.eatExpression()); } else { dimensions.add((Object)null); } } if (this.maybeEatInlineList()) { nodes.add(this.pop()); } this.push(new ConstructorReference(this.toPos(newToken), (SpelNodeImpl[])dimensions.toArray(new SpelNodeImpl[dimensions.size()]), (SpelNodeImpl[])nodes.toArray(new SpelNodeImpl[nodes.size()]))); } else { this.eatConstructorArgs(nodes); this.push(new ConstructorReference(this.toPos(newToken), (SpelNodeImpl[])nodes.toArray(new SpelNodeImpl[nodes.size()]))); } return true; } } private void push(SpelNodeImpl newNode) { this.constructedNodes.push(newNode); } private SpelNodeImpl pop() { return (SpelNodeImpl)this.constructedNodes.pop(); } private boolean maybeEatLiteral() { Token t = this.peekToken(); if (t == null) { return false; } else { if (t.kind == TokenKind.LITERAL_INT) { this.push(Literal.getIntLiteral(t.data, this.toPos(t), 10)); } else if (t.kind == TokenKind.LITERAL_LONG) { this.push(Literal.getLongLiteral(t.data, this.toPos(t), 10)); } else if (t.kind == TokenKind.LITERAL_HEXINT) { this.push(Literal.getIntLiteral(t.data, this.toPos(t), 16)); } else if (t.kind == TokenKind.LITERAL_HEXLONG) { this.push(Literal.getLongLiteral(t.data, this.toPos(t), 16)); } else if (t.kind == TokenKind.LITERAL_REAL) { this.push(Literal.getRealLiteral(t.data, this.toPos(t), false)); } else if (t.kind == TokenKind.LITERAL_REAL_FLOAT) { this.push(Literal.getRealLiteral(t.data, this.toPos(t), true)); } else if (this.peekIdentifierToken("true")) { this.push(new BooleanLiteral(t.data, this.toPos(t), true)); } else if (this.peekIdentifierToken("false")) { this.push(new BooleanLiteral(t.data, this.toPos(t), false)); } else { if (t.kind != TokenKind.LITERAL_STRING) { return false; } this.push(new StringLiteral(t.data, this.toPos(t), t.data)); } this.nextToken(); return true; } } private boolean maybeEatParenExpression() { if (this.peekToken(TokenKind.LPAREN)) { this.nextToken(); SpelNodeImpl expr = this.eatExpression(); this.eatToken(TokenKind.RPAREN); this.push(expr); return true; } else { return false; } } private Token maybeEatRelationalOperator() { Token t = this.peekToken(); if (t == null) { return null; } else if (t.isNumericRelationalOperator()) { return t; } else { if (t.isIdentifier()) { String idString = t.stringValue(); if (idString.equalsIgnoreCase("instanceof")) { return t.asInstanceOfToken(); } if (idString.equalsIgnoreCase("matches")) { return t.asMatchesToken(); } if (idString.equalsIgnoreCase("between")) { return t.asBetweenToken(); } } return null; } } private Token eatToken(TokenKind expectedKind) { Token t = this.nextToken(); if (t == null) { this.raiseInternalException(this.expressionString.length(), SpelMessage.OOD); } if (t.kind != expectedKind) { this.raiseInternalException(t.startpos, SpelMessage.NOT_EXPECTED_TOKEN, expectedKind.toString().toLowerCase(), t.getKind().toString().toLowerCase()); } return t; } private boolean peekToken(TokenKind desiredTokenKind) { return this.peekToken(desiredTokenKind, false); } private boolean peekToken(TokenKind desiredTokenKind, boolean consumeIfMatched) { if (!this.moreTokens()) { return false; } else { Token t = this.peekToken(); if (t.kind == desiredTokenKind) { if (consumeIfMatched) { ++this.tokenStreamPointer; } return true; } else { return desiredTokenKind == TokenKind.IDENTIFIER && t.kind.ordinal() >= TokenKind.DIV.ordinal() && t.kind.ordinal() <= TokenKind.NOT.ordinal() && t.data != null; } } } private boolean peekToken(TokenKind possible1, TokenKind possible2) { if (!this.moreTokens()) { return false; } else { Token t = this.peekToken(); return t.kind == possible1 || t.kind == possible2; } } private boolean peekToken(TokenKind possible1, TokenKind possible2, TokenKind possible3) { if (!this.moreTokens()) { return false; } else { Token t = this.peekToken(); return t.kind == possible1 || t.kind == possible2 || t.kind == possible3; } } private boolean peekIdentifierToken(String identifierString) { if (!this.moreTokens()) { return false; } else { Token t = this.peekToken(); return t.kind == TokenKind.IDENTIFIER && t.stringValue().equalsIgnoreCase(identifierString); } } private boolean peekSelectToken() { if (!this.moreTokens()) { return false; } else { Token t = this.peekToken(); return t.kind == TokenKind.SELECT || t.kind == TokenKind.SELECT_FIRST || t.kind == TokenKind.SELECT_LAST; } } private boolean moreTokens() { return this.tokenStreamPointer < this.tokenStream.size(); } private Token nextToken() { return this.tokenStreamPointer >= this.tokenStreamLength ? null : (Token)this.tokenStream.get(this.tokenStreamPointer++); } private Token peekToken() { return this.tokenStreamPointer >= this.tokenStreamLength ? null : (Token)this.tokenStream.get(this.tokenStreamPointer); } private void raiseInternalException(int pos, SpelMessage message, Object... inserts) { throw new InternalParseException(new SpelParseException(this.expressionString, pos, message, inserts)); } public String toString(Token t) { return t.getKind().hasPayload() ? t.stringValue() : t.kind.toString().toLowerCase(); } private void checkOperands(Token token, SpelNodeImpl left, SpelNodeImpl right) { this.checkLeftOperand(token, left); this.checkRightOperand(token, right); } private void checkLeftOperand(Token token, SpelNodeImpl operandExpression) { if (operandExpression == null) { this.raiseInternalException(token.startpos, SpelMessage.LEFT_OPERAND_PROBLEM); } } private void checkRightOperand(Token token, SpelNodeImpl operandExpression) { if (operandExpression == null) { this.raiseInternalException(token.startpos, SpelMessage.RIGHT_OPERAND_PROBLEM); } } private int toPos(Token t) { return (t.startpos << 16) + t.endpos; } private int toPos(int start, int end) { return (start << 16) + end; } }
1.3 源码解析为何算出666?
https://blog.csdn.net/f641385712/article/details/90812967
诸葛