Browse Source

Support decimal constants with trailing [dD] in painless (#21412)

This adds support to painless for decimal constants with trailing `d` or
`D` to make it compatible with Java. It already supported integer
constants with a trailing `d` or `D` but this adds tests for it.

Closes #21116
Nik Everett 9 years ago
parent
commit
2a328034ef

+ 1 - 1
modules/lang-painless/src/main/antlr/PainlessLexer.g4

@@ -103,7 +103,7 @@ AUSH:   '>>>=';
 OCTAL: '0' [0-7]+ [lL]?;
 HEX: '0' [xX] [0-9a-fA-F]+ [lL]?;
 INTEGER: ( '0' | [1-9] [0-9]* ) [lLfFdD]?;
-DECIMAL: ( '0' | [1-9] [0-9]* ) (DOT [0-9]+)? ( [eE] [+\-]? [0-9]+ )? [fF]?;
+DECIMAL: ( '0' | [1-9] [0-9]* ) (DOT [0-9]+)? ( [eE] [+\-]? [0-9]+ )? [fFdD]?;
 
 STRING: ( '"' ( '\\"' | '\\\\' | ~[\\"] )*? '"' ) | ( '\'' ( '\\\'' | '\\\\' | ~[\\"] )*? '\'' );
 REGEX: '/' ( ~('/' | '\n') | '\\' ~'\n' )+ '/' [cilmsUux]* { SlashStrategy.slashIsRegex(this) }?;

+ 15 - 15
modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/PainlessLexer.java

@@ -204,21 +204,21 @@ class PainlessLexer extends Lexer {
     "~@\u0080A\u0082B\u0084C\u0086D\u0088E\u008aF\u008cG\u008eH\u0090I\u0092"+
     "J\u0094K\u0096L\u0098M\u009aN\u009cO\u009eP\u00a0Q\u00a2R\u00a4S\u00a6"+
     "T\4\2\3\24\5\2\13\f\17\17\"\"\4\2\f\f\17\17\3\2\629\4\2NNnn\4\2ZZzz\5"+
-    "\2\62;CHch\3\2\63;\3\2\62;\b\2FFHHNNffhhnn\4\2GGgg\4\2--//\4\2HHhh\4\2"+
-    "$$^^\4\2\f\f\61\61\3\2\f\f\t\2WWeekknouuwwzz\5\2C\\aac|\6\2\62;C\\aac"+
-    "|\u026b\2\4\3\2\2\2\2\6\3\2\2\2\2\b\3\2\2\2\2\n\3\2\2\2\2\f\3\2\2\2\2"+
-    "\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2\2\2\24\3\2\2\2\2\26\3\2\2\2\2\30\3"+
-    "\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2\36\3\2\2\2\2 \3\2\2\2\2\"\3\2\2\2\2"+
-    "$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2*\3\2\2\2\2,\3\2\2\2\2.\3\2\2\2\2\60"+
-    "\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2\2\66\3\2\2\2\28\3\2\2\2\2:\3\2\2\2"+
-    "\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2\2H"+
-    "\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T\3\2"+
-    "\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3\2\2"+
-    "\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2h\3\2\2\2\2j\3\2\2\2\2l\3\2\2\2\2"+
-    "n\3\2\2\2\2p\3\2\2\2\2r\3\2\2\2\2t\3\2\2\2\2v\3\2\2\2\2x\3\2\2\2\2z\3"+
-    "\2\2\2\2|\3\2\2\2\2~\3\2\2\2\2\u0080\3\2\2\2\2\u0082\3\2\2\2\2\u0084\3"+
-    "\2\2\2\2\u0086\3\2\2\2\2\u0088\3\2\2\2\2\u008a\3\2\2\2\2\u008c\3\2\2\2"+
-    "\2\u008e\3\2\2\2\2\u0090\3\2\2\2\2\u0092\3\2\2\2\2\u0094\3\2\2\2\2\u0096"+
+    "\2\62;CHch\3\2\63;\3\2\62;\b\2FFHHNNffhhnn\4\2GGgg\4\2--//\6\2FFHHffh"+
+    "h\4\2$$^^\4\2\f\f\61\61\3\2\f\f\t\2WWeekknouuwwzz\5\2C\\aac|\6\2\62;C"+
+    "\\aac|\u026b\2\4\3\2\2\2\2\6\3\2\2\2\2\b\3\2\2\2\2\n\3\2\2\2\2\f\3\2\2"+
+    "\2\2\16\3\2\2\2\2\20\3\2\2\2\2\22\3\2\2\2\2\24\3\2\2\2\2\26\3\2\2\2\2"+
+    "\30\3\2\2\2\2\32\3\2\2\2\2\34\3\2\2\2\2\36\3\2\2\2\2 \3\2\2\2\2\"\3\2"+
+    "\2\2\2$\3\2\2\2\2&\3\2\2\2\2(\3\2\2\2\2*\3\2\2\2\2,\3\2\2\2\2.\3\2\2\2"+
+    "\2\60\3\2\2\2\2\62\3\2\2\2\2\64\3\2\2\2\2\66\3\2\2\2\28\3\2\2\2\2:\3\2"+
+    "\2\2\2<\3\2\2\2\2>\3\2\2\2\2@\3\2\2\2\2B\3\2\2\2\2D\3\2\2\2\2F\3\2\2\2"+
+    "\2H\3\2\2\2\2J\3\2\2\2\2L\3\2\2\2\2N\3\2\2\2\2P\3\2\2\2\2R\3\2\2\2\2T"+
+    "\3\2\2\2\2V\3\2\2\2\2X\3\2\2\2\2Z\3\2\2\2\2\\\3\2\2\2\2^\3\2\2\2\2`\3"+
+    "\2\2\2\2b\3\2\2\2\2d\3\2\2\2\2f\3\2\2\2\2h\3\2\2\2\2j\3\2\2\2\2l\3\2\2"+
+    "\2\2n\3\2\2\2\2p\3\2\2\2\2r\3\2\2\2\2t\3\2\2\2\2v\3\2\2\2\2x\3\2\2\2\2"+
+    "z\3\2\2\2\2|\3\2\2\2\2~\3\2\2\2\2\u0080\3\2\2\2\2\u0082\3\2\2\2\2\u0084"+
+    "\3\2\2\2\2\u0086\3\2\2\2\2\u0088\3\2\2\2\2\u008a\3\2\2\2\2\u008c\3\2\2"+
+    "\2\2\u008e\3\2\2\2\2\u0090\3\2\2\2\2\u0092\3\2\2\2\2\u0094\3\2\2\2\2\u0096"+
     "\3\2\2\2\2\u0098\3\2\2\2\2\u009a\3\2\2\2\2\u009c\3\2\2\2\2\u009e\3\2\2"+
     "\2\2\u00a0\3\2\2\2\2\u00a2\3\2\2\2\3\u00a4\3\2\2\2\3\u00a6\3\2\2\2\4\u00a9"+
     "\3\2\2\2\6\u00c4\3\2\2\2\b\u00c8\3\2\2\2\n\u00ca\3\2\2\2\f\u00cc\3\2\2"+

+ 1 - 1
modules/lang-painless/src/main/java/org/elasticsearch/painless/antlr/StashingTokenFactory.java

@@ -27,7 +27,7 @@ import org.antlr.v4.runtime.TokenSource;
 import org.antlr.v4.runtime.misc.Pair;
 
 /**
- * Token factory that preseres that last non-whitespace token so you can do token level lookbehind in the lexer.
+ * Token factory that preserves that last non-whitespace token so you can do token level lookbehind in the lexer.
  */
 public class StashingTokenFactory<T extends Token> implements TokenFactory<T> {
     private final TokenFactory<T> delegate;

+ 5 - 1
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EDecimal.java

@@ -58,8 +58,12 @@ public final class EDecimal extends AExpression {
                 throw createError(new IllegalArgumentException("Invalid float constant [" + value + "]."));
             }
         } else {
+            String toParse = value;
+            if (toParse.endsWith("d") || value.endsWith("D")) {
+                toParse = toParse.substring(0, value.length() - 1);
+            }
             try {
-                constant = Double.parseDouble(value);
+                constant = Double.parseDouble(toParse);
                 actual = Definition.DOUBLE_TYPE;
             } catch (NumberFormatException exception) {
                 throw createError(new IllegalArgumentException("Invalid double constant [" + value + "]."));

+ 18 - 10
modules/lang-painless/src/test/java/org/elasticsearch/painless/BasicExpressionTests.java

@@ -27,16 +27,24 @@ public class BasicExpressionTests extends ScriptTestCase {
 
     /** simple tests returning a constant value */
     public void testReturnConstant() {
-        assertEquals(5, exec("return 5;"));
-        assertEquals(7L, exec("return 7L;"));
-        assertEquals(7.0, exec("return 7.0;"));
-        assertEquals(32.0F, exec("return 32.0F;"));
-        assertEquals((byte)255, exec("return (byte)255;"));
-        assertEquals((short)5, exec("return (short)5;"));
-        assertEquals("string", exec("return \"string\";"));
-        assertEquals(true, exec("return true;"));
-        assertEquals(false, exec("return false;"));
-        assertNull(exec("return null;"));
+        assertEquals(5, exec("return 5"));
+        assertEquals(6L, exec("return 6l"));
+        assertEquals(7L, exec("return 7L"));
+        assertEquals(7.0d, exec("return 7.0"));
+        assertEquals(18.0d, exec("return 18d"));
+        assertEquals(19.0d, exec("return 19.0d"));
+        assertEquals(20.0d, exec("return 20D"));
+        assertEquals(21.0d, exec("return 21.0D"));
+        assertEquals(32.0F, exec("return 32.0f"));
+        assertEquals(33.0F, exec("return 33f"));
+        assertEquals(34.0F, exec("return 34.0F"));
+        assertEquals(35.0F, exec("return 35F"));
+        assertEquals((byte)255, exec("return (byte)255"));
+        assertEquals((short)5, exec("return (short)5"));
+        assertEquals("string", exec("return \"string\""));
+        assertEquals(true, exec("return true"));
+        assertEquals(false, exec("return false"));
+        assertNull(exec("return null"));
     }
 
     public void testReturnConstantChar() {