SPR-5518: textual alternatives for operators (eq, lt, le, gt, ge, ne, div, mod, not) - removes messy escaping for expressions declared in XML.
This commit is contained in:
@@ -267,10 +267,10 @@ public class SpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
|
||||
// unaryExpression: (PLUS^ | MINUS^ | BANG^) unaryExpression | primaryExpression ;
|
||||
private SpelNodeImpl eatUnaryExpression() {
|
||||
if (peekToken(TokenKind.PLUS,TokenKind.MINUS,TokenKind.BANG)) {
|
||||
if (peekToken(TokenKind.PLUS,TokenKind.MINUS,TokenKind.NOT)) {
|
||||
Token t = nextToken();
|
||||
SpelNodeImpl expr = eatUnaryExpression();
|
||||
if (t.kind==TokenKind.BANG) {
|
||||
if (t.kind==TokenKind.NOT) {
|
||||
return new OperatorNot(toPos(t),expr);
|
||||
} else if (t.kind==TokenKind.PLUS) {
|
||||
return new OpPlus(toPos(t),expr);
|
||||
|
||||
@@ -24,7 +24,7 @@ enum TokenKind {
|
||||
LITERAL_INT, LITERAL_LONG, LITERAL_HEXINT, LITERAL_HEXLONG, LITERAL_STRING, LITERAL_REAL, LITERAL_REAL_FLOAT,
|
||||
LPAREN("("), RPAREN(")"), COMMA(","), IDENTIFIER,
|
||||
COLON(":"),HASH("#"),RSQUARE("]"), LSQUARE("["),
|
||||
DOT("."), PLUS("+"), STAR("*"), DIV("/"), BANG("!"), MINUS("-"), SELECT_FIRST("^["), SELECT_LAST("$["), QMARK("?"), PROJECT("!["),
|
||||
DOT("."), PLUS("+"), STAR("*"), DIV("/"), NOT("!"), MINUS("-"), SELECT_FIRST("^["), SELECT_LAST("$["), QMARK("?"), PROJECT("!["),
|
||||
GE(">="),GT(">"),LE("<="),LT("<"),EQ("=="),NE("!="),ASSIGN("="), INSTANCEOF("instanceof"), MATCHES("matches"), BETWEEN("between"),
|
||||
SELECT("?["), MOD("%"), POWER("^"), DOLLAR("$"),
|
||||
ELVIS("?:"), SAFE_NAVI("?.");
|
||||
@@ -49,4 +49,8 @@ enum TokenKind {
|
||||
public boolean hasPayload() {
|
||||
return hasPayload;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return tokenChars.length;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.expression.spel.standard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
@@ -102,7 +103,7 @@ public class Tokenizer {
|
||||
} else if (isTwoCharToken(TokenKind.PROJECT)) {
|
||||
pushPairToken(TokenKind.PROJECT);
|
||||
} else {
|
||||
pushCharToken(TokenKind.BANG);
|
||||
pushCharToken(TokenKind.NOT);
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
@@ -329,13 +330,26 @@ public class Tokenizer {
|
||||
}
|
||||
}
|
||||
|
||||
// if this is changed, it must remain sorted
|
||||
private static final String[] alternativeOperatorNames = { "DIV","EQ","GE","GT","LE","LT","MOD","NE","NOT"};
|
||||
|
||||
private void lexIdentifier() {
|
||||
int start = pos;
|
||||
do {
|
||||
pos++;
|
||||
} while (isIdentifier(toProcess[pos]));
|
||||
tokens.add(new Token(TokenKind.IDENTIFIER,subarray(start,pos),start,pos));
|
||||
char[] subarray = subarray(start,pos);
|
||||
|
||||
// Check if this is the alternative (textual) representation of an operator (see alternativeOperatorNames)
|
||||
if ((pos-start)==2 || (pos-start)==3) {
|
||||
String asString = new String(subarray).toUpperCase();
|
||||
int idx = Arrays.binarySearch(alternativeOperatorNames,asString);
|
||||
if (idx>=0) {
|
||||
pushOneCharOrTwoCharToken(TokenKind.valueOf(asString),start);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tokens.add(new Token(TokenKind.IDENTIFIER,subarray,start,pos));
|
||||
}
|
||||
|
||||
private void pushIntToken(char[] data,boolean isLong, int start, int end) {
|
||||
@@ -399,6 +413,10 @@ public class Tokenizer {
|
||||
tokens.add(new Token(kind,pos,pos+2));
|
||||
pos+=2;
|
||||
}
|
||||
|
||||
private void pushOneCharOrTwoCharToken(TokenKind kind, int pos) {
|
||||
tokens.add(new Token(kind,pos,pos+kind.getLength()));
|
||||
}
|
||||
|
||||
// ID: ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|DOT_ESCAPED)*;
|
||||
private boolean isIdentifier(char ch) {
|
||||
|
||||
Reference in New Issue
Block a user