SLING-7701 - [HTL] Add support for negative numbers
diff --git a/src/main/antlr4/org/apache/sling/scripting/sightly/impl/parser/expr/generated/SightlyLexer.g4 b/src/main/antlr4/org/apache/sling/scripting/sightly/impl/parser/expr/generated/SightlyLexer.g4
index 255fb2a..429dfb4 100644
--- a/src/main/antlr4/org/apache/sling/scripting/sightly/impl/parser/expr/generated/SightlyLexer.g4
+++ b/src/main/antlr4/org/apache/sling/scripting/sightly/impl/parser/expr/generated/SightlyLexer.g4
@@ -74,16 +74,17 @@
// tokens
-ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|':')*
+ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|':')*
;
-INT : '0'..'9'+
+INT : '-'? '1'..'9'+ '0'..'9'*
+ | '0'
;
FLOAT
- : ('0'..'9')+ '.' ('0'..'9')+ EXPONENT?
-// | '.' ('0'..'9')+ EXPONENT? --> conflicts with a.2 notation
- | ('0'..'9')+ EXPONENT
+ : '-'? '1'..'9'+ '0'..'9'* '.' '0'..'9'+ EXPONENT?
+ | '-'? '0.' '0'..'9'+ EXPONENT?
+ | '-'? '1'..'9'+ '0'..'9'* EXPONENT
;
COMMENT: '<!--/*' .*? '*/-->' -> skip;
diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/NumericConstant.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/NumericConstant.java
index d03056c..cee38a0 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/NumericConstant.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/NumericConstant.java
@@ -80,8 +80,12 @@
}
private Number parseNumber(String s) {
- if (s.contains(".")) {
- return Double.parseDouble(s);
+ if (s.contains(".") || s.contains("e") || s.contains("E")) {
+ double interim = Double.parseDouble(s);
+ if (interim == 0) {
+ return 0.0;
+ }
+ return interim;
}
return Long.parseLong(s);
}
diff --git a/src/test/java/org/apache/sling/scripting/sightly/impl/TestUtils.java b/src/test/java/org/apache/sling/scripting/sightly/impl/TestUtils.java
deleted file mode 100644
index bcc014a..0000000
--- a/src/test/java/org/apache/sling/scripting/sightly/impl/TestUtils.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.sling.scripting.sightly.impl;
-
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-
-import org.apache.sling.scripting.sightly.compiler.CompilationUnit;
-
-/**
- * Testing static utilities that simplify writing tests for the HTL compiler.
- */
-public class TestUtils {
-
- public static CompilationUnit readScriptFromClasspath(final String scriptResource) {
- InputStream stream = TestUtils.class.getResourceAsStream(scriptResource);
- final Reader reader = new InputStreamReader(stream);
- return new CompilationUnit() {
- @Override
- public String getScriptName() {
- return scriptResource;
- }
-
- @Override
- public Reader getScriptReader() {
- return reader;
- }
- };
- }
-}
diff --git a/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyCompilerTest.java b/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyCompilerTest.java
index e861b5f..7d95e1d 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyCompilerTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyCompilerTest.java
@@ -18,13 +18,16 @@
******************************************************************************/
package org.apache.sling.scripting.sightly.impl.compiler;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
import java.util.List;
import org.apache.sling.scripting.sightly.compiler.CompilationResult;
import org.apache.sling.scripting.sightly.compiler.CompilationUnit;
import org.apache.sling.scripting.sightly.compiler.CompilerMessage;
import org.apache.sling.scripting.sightly.compiler.SightlyCompiler;
-import org.apache.sling.scripting.sightly.impl.TestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
@@ -42,7 +45,7 @@
@Test
public void testEmptyExpression() {
- CompilationResult result = compile("/empty-expression.html");
+ CompilationResult result = compileFile("/empty-expression.html");
assertTrue("Didn't expect any warnings or errors.", result.getErrors().size() == 0 && result.getWarnings().size() == 0);
}
@@ -55,7 +58,7 @@
}
private void testMissingExplicitContext(String script) {
- CompilationResult result = compile(script);
+ CompilationResult result = compileFile(script);
List<CompilerMessage> warnings = result.getWarnings();
assertTrue(script + ": Expected compilation warnings.", warnings.size() == 1);
CompilerMessage warningMessage = warnings.get(0);
@@ -91,7 +94,7 @@
@Test
public void testSensitiveAttributes() {
String script = "/sensitive-attributes.html";
- CompilationResult result = compile(script);
+ CompilationResult result = compileFile(script);
List<CompilerMessage> warnings = result.getWarnings();
assertTrue("Expected compilation warnings.", warnings.size() == 2);
CompilerMessage _1stWarning = warnings.get(0);
@@ -110,15 +113,72 @@
@Test
public void testErrorReporting1() {
String script = "/error-1.html";
- CompilationResult result = compile(script);
+ CompilationResult result = compileFile(script);
List<CompilerMessage> errors = result.getErrors();
assertTrue("Expected compilation errors.", errors.size() == 1);
CompilerMessage error = errors.get(0);
assertEquals("Error is not reported at the expected line.", 18, error.getLine());
}
- private CompilationResult compile(String file) {
- CompilationUnit compilationUnit = TestUtils.readScriptFromClasspath(file);
+ @Test
+ public void testNumberParsing() {
+ // integers
+ int integerTestRange = 20;
+ for (int i = -1 * integerTestRange; i < integerTestRange; i++) {
+ assertEquals(0, compileSource("${" + i + "}").getErrors().size());
+ }
+
+ // doubles
+ double doubleTestRange = 20.00;
+ for (double i = -1.00 * doubleTestRange; i < doubleTestRange; i+= 0.1) {
+ assertEquals(0, compileSource("${" + i + "}").getErrors().size());
+ }
+
+ assertEquals(0, compileSource("${-0.0}").getErrors().size());
+ assertEquals(0, compileSource("${-0.000}").getErrors().size());
+ assertEquals(1, compileSource("${-00.0}").getErrors().size());
+ assertEquals(1, compileSource("${00.0}").getErrors().size());
+ assertEquals(1, compileSource("${00}").getErrors().size());
+ assertEquals(1, compileSource("${-0}").getErrors().size());
+ assertEquals(1, compileSource("${01}").getErrors().size());
+ assertEquals(0, compileSource("${0.1e-2}").getErrors().size());
+ assertEquals(0, compileSource("${0.1e+2}").getErrors().size());
+ assertEquals(1, compileSource("${00.1e-2}").getErrors().size());
+ assertEquals(1, compileSource("${0e-2}").getErrors().size());
+ assertEquals(1, compileSource("${01e-2}").getErrors().size());
+ assertEquals(0, compileSource("${1e-2}").getErrors().size());
+ assertEquals(0, compileSource("${1e+2}").getErrors().size());
+ }
+
+ private CompilationResult compileFile(final String file) {
+ InputStream stream = this.getClass().getResourceAsStream(file);
+ final Reader reader = new InputStreamReader(stream);
+ CompilationUnit compilationUnit = new CompilationUnit() {
+ @Override
+ public String getScriptName() {
+ return file;
+ }
+
+ @Override
+ public Reader getScriptReader() {
+ return reader;
+ }
+ };
+ return compiler.compile(compilationUnit);
+ }
+
+ private CompilationResult compileSource(final String source) {
+ CompilationUnit compilationUnit = new CompilationUnit() {
+ @Override
+ public String getScriptName() {
+ return "NO_NAME";
+ }
+
+ @Override
+ public Reader getScriptReader() {
+ return new StringReader(source);
+ }
+ };
return compiler.compile(compilationUnit);
}