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:
Andy Clement
2009-07-06 18:53:48 +00:00
parent e77e070e7a
commit ea2580af68
6 changed files with 85 additions and 10 deletions

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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) {